Мы выполняем запрос к находящейся в памяти коллекции объектов данных LINQ. Проблема заключается в том, что мы упорядочиваем по столбцу в связанной таблице, записи которого еще не обязательно были загружены (отложенная загрузка:)
Dim oPkgProducts = _
From b In oBillPkg.BillProducts _
Where b.Successful.GetValueOrDefault(Common.X_INDETERMINATE) = _
Common.X_INDETERMINATE _
Order By _
b.ProductFromCache.ProvisionCodePriority.ProvisionPriority Ascending _
Select b
Мы зафиксировали следующую ошибку в производственном процессе, когда код попытался вызвать Count () для этого запроса:
System.ArgumentException: элемент с
тот же ключ уже был добавлен.
в
System.ThrowHelper.ThrowArgumentException (ExceptionResource
ресурс) в
System.Collections.Generic.Dictionary 2.Insert(TKey
key, TValue value, Boolean add) at
System.Data.Linq.IdentityManager.StandardIdentityManager.SetCurrent(MetaType
type) at
System.Data.Linq.IdentityManager.StandardIdentityManager.Find(MetaType
type, Object[] keyValues) at
System.Data.Linq.CommonDataServices.GetCachedObject(MetaType
type, Object[] keyValues) at
System.Data.Linq.CommonDataServices.DeferredSourceFactory
1.TryGetCached
Object (Object [] keyValues, T & cached)
в
System.Data.Linq.CommonDataServices.DeferredSourceFactory 1.Execute(Object
instance) at
System.Data.Linq.CommonDataServices.DeferredSourceFactory
1.DeferredSource.GetEnumerator ()
в
System.Linq.Enumerable.SingleOrDefault [TSource] (IEnumerable 1
source) at
System.Data.Linq.EntityRef
1.get_Entity ()
в
PackageManagement.Product.get_ProvisionCodePriority ()
в
C: \ Проекты \ библиотеки DLL \ DotNet35 \ PackageManagement \ PackageManagement.designer.vb: линия
14431 в
ProvisionEngine.BillPackageProvision. Lambda $ _12 (BillProduct
б) в
C: \ Projects \ библиотеки DLL \ DotNet35 \ ProvisionEngine \ BillPackageProvision.vb: линия
394 в
System.Linq.EnumerableSorter 2.ComputeKeys(TElement[]
elements, Int32 count) at
System.Linq.EnumerableSorter
1.Sort (TElement []
элементы, число Int32) в
System.Linq.OrderedEnumerable 1.<GetEnumerator>d__0.MoveNext()
at
System.Linq.Enumerable.WhereSelectEnumerableIterator
2.MoveNext ()
в
System.Linq.Enumerable.Count [TSource] (IEnumerable`1
источник) в
ProvisionEngine.BillPackageProvision.ProvisionPackage (BillPackage
oBillPkg, Boolean bRecursiveCall) в
C: \ Projects \ библиотеки DLL \ DotNet35 \ ProvisionEngine \ BillPackageProvision.vb: линия
397
Запутанная часть заключается в том, что когда операция была автоматически повторена через несколько секунд, она прошла успешно. И поскольку это единственное время, когда мы видели исключение (в остальное время код работает нормально), воспроизвести его будет нелегко.
Некоторые сведения: «ProductFromCache» - это вспомогательное свойство, которое использует технику Пита Монтгомери для реализации кеша LINQ to SQL . Код может быть переписан для использования свойства LINQ .Product по умолчанию. Я не думаю, что это является частью проблемы, потому что трассировка стека показывает, что исключение происходит внутри библиотек .NET System. Я думаю, что исключение происходит, когда вызывается свойство .ProvisionCodePriority - это возвращает запись из таблицы, связанной с таблицей продукта. Похоже, что LINQ пытается кэшировать результат этой отложенной загрузки в универсальном объекте Dictionary. Но по какой-то причине словарь уже содержит указанный ключ.
У кого-нибудь есть идея, почему это может происходить?