title: "System.ArgumentException: An item with the same key has already been added." when trying to order an in-memory LINQ query by a LINQ association
body: <p>We are doing a query against an in-memory collection of LINQ data objects. The wrinkle is that we are ordering by a column in a related table whose records have not necessarily been loaded yet (deferred loading:)</p>
  
  <pre><code>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
  </code></pre>
  
  <p>We logged the following error in production when the code tried to call Count() on this query:</p>
  
  <blockquote>
    <p>System.ArgumentException: An item with
    the same key has already been added.
    at
    System.ThrowHelper.ThrowArgumentException(ExceptionResource
    resource) at
    System.Collections.Generic.Dictionary<code>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</code>1.TryGetCached
    Object(Object[] keyValues, T&amp; cached)
    at
    System.Data.Linq.CommonDataServices.DeferredSourceFactory<code>1.Execute(Object
    instance) at
    System.Data.Linq.CommonDataServices.DeferredSourceFactory</code>1.DeferredSource.GetEnumerator()
    at
    System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable<code>1
    source) at
    System.Data.Linq.EntityRef</code>1.get_Entity()
    at
    PackageManagement.Product.get_ProvisionCodePriority()
    in
    C:\Projects\DLLs\DotNet35\PackageManagement\PackageManagement.designer.vb:line
    14431 at
    ProvisionEngine.BillPackageProvision.<em>Lambda$</em>_12(BillProduct
    b) in
    C:\Projects\DLLs\DotNet35\ProvisionEngine\BillPackageProvision.vb:line
    394 at
    System.Linq.EnumerableSorter<code>2.ComputeKeys(TElement[]
    elements, Int32 count) at
    System.Linq.EnumerableSorter</code>1.Sort(TElement[]
    elements, Int32 count) at
    System.Linq.OrderedEnumerable<code>1.&lt;GetEnumerator&gt;d__0.MoveNext()
    at
    System.Linq.Enumerable.WhereSelectEnumerableIterator</code>2.MoveNext()
    at
    System.Linq.Enumerable.Count[TSource](IEnumerable`1
    source) at
    ProvisionEngine.BillPackageProvision.ProvisionPackage(BillPackage
    oBillPkg, Boolean bRecursiveCall) in
    C:\Projects\DLLs\DotNet35\ProvisionEngine\BillPackageProvision.vb:line
    397</p>
  </blockquote>
  
  <p>The confusing part is that when the operation was automatically retried a few seconds later, it succeeded. And since this is the only time we've seen the exception (the code runs fine the rest of the time) it is not going to be easy to reproduce.</p>
  
  <p>Some background: "ProductFromCache" is a helper property that uses <a href="http://petemontgomery.wordpress.com/2008/08/07/caching-the-results-of-linq-queries/" rel="nofollow">Pete Montgomery's technique for implementing a LINQ to SQL cache</a>. The code could be rewritten to use the default LINQ .Product property too. I don't think this is part of the problem because the stack trace shows that the exception is happening inside .NET System libraries. I think the exception is happening when the .ProvisionCodePriority property is called -- this returns a record from a table associated to the product table. LINQ seems to be trying to cache the result of this deferred load in a generic Dictionary object. But for some reason, the Dictionary already contains the specified key.</p>
  
  <p>Does anyone have an idea why this might be happening?</p>