2

専門家、

実行時にエンティティ フレームワーク関数を初めて使用するときに、このSystem.ArgumentException (同じキーを持つ項目が既に追加されています) を取得しています。奇妙なこと: デバッグ モードを使用している場合、問題なく動作します。リリース モードで変更を加えずに同じコードをコンパイルすると、この投稿の冒頭に記載されている例外を除いて、すぐにクラッシュします。

誰かがそのような奇妙な行動についてもっと知っていますか? どうすれば修正できますか?デバッグ バージョンを顧客に公開できません :(

この時点で例外がスローされます。

try
{
  var blub = context.ExecuteStoreQuery<int>(QueryString);
}
catch (Exception ex)
{
  // ...
}    

スタックトレース:

System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boo
lean add)
   at System.Data.Metadata.Edm.ObjectItemAttributeAssemblyLoader.LoadRelationshi
pTypes()
   at System.Data.Metadata.Edm.ObjectItemAttributeAssemblyLoader.LoadTypesFromAs
sembly()
   at System.Data.Metadata.Edm.ObjectItemAssemblyLoader.Load()
   at System.Data.Metadata.Edm.ObjectItemAttributeAssemblyLoader.Load()
   at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boo
lean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
   at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boo
lean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
   at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boo
lean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
   at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boo
lean loadReferencedAssemblies, ObjectItemLoadingSessionData loadingData)
   at System.Data.Metadata.Edm.AssemblyCache.LoadAssembly(Assembly assembly, Boo
lean loadReferencedAssemblies, KnownAssembliesSet knownAssemblies, EdmItemCollec
tion edmItemCollection, Action`1 logLoadMessage, Object& loaderCookie, Dictionar
y`2& typesInLoading, List`1& errors)
   at System.Data.Metadata.Edm.ObjectItemCollection.LoadAssemblyFromCache(Object
ItemCollection objectItemCollection, Assembly assembly, Boolean loadReferencedAs
semblies, EdmItemCollection edmItemCollection, Action`1 logLoadMessage)
   at System.Data.Metadata.Edm.MetadataWorkspace.ImplicitLoadAssemblyForType(Typ
e type, Assembly callingAssembly)
   at System.Data.Objects.ObjectContext.ExecuteStoreQueryInternal[TElement](Stri
ng commandText, String entitySetName, MergeOption mergeOption, Object[] paramete
rs)
4

1 に答える 1

2

まず、クリーン リリース ビルドを作成してもエラーが発生することを確認します(つまり、ビルドを実行する前にバイナリがないこと、ソース コードのみ)。そうでない場合は、プロジェクトのセットアップを修正します (たとえば、デバッグ ターゲット フォルダーとリリース ビルド ターゲット フォルダーを分離します)。

エラーが 1 回だけ発生し、その後アプリが正常に動作する場合は、同期の問題が発生している可能性があります。かなり奇妙ですが、メタデータの読み込みは同期されているようです。ただし、いずれにしても、EF オブジェクトはスレッドセーフではありません。クロススレッド シナリオでは使用しないでください。

上記が役に立たない場合は、私の研究の結果が役立つかもしれません。エラーに関連する EF ソース コードからの抜粋を次に示します。

//---------------------------------------------------------------------- 
// <copyright file="ObjectItemAttributeAssemblyLoader.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Objects.DataClasses;
using System.Diagnostics; 
using System.Reflection;

namespace System.Data.Metadata.Edm 
{
  /// <summary> 
  /// Class for representing a collection of items for the object layer.
  /// Most of the implemetation for actual maintainance of the collection is
  /// done by ItemCollection
  /// </summary> 
  internal sealed class ObjectItemAttributeAssemblyLoader :
      ObjectItemAssemblyLoader
  { 
    // ...

    /// <summary>
    /// This method loads all the relationship type that this entity takes part in
    /// </summary> 
    /// <param name="entityType"></param>
    /// <param name="context"></param> 
    private void LoadRelationshipTypes() 
    {
      foreach (EdmRelationshipAttribute roleAttribute in
               SourceAssembly.GetCustomAttributes(typeof(EdmRelationshipAttribute), false /*inherit*/)) 
      {
        // Check if there is an entry already with this name
        if (TryFindNullParametersInRelationshipAttribute(roleAttribute))
        { 
          // don't give more errors for these same bad parameters
          continue; 
        } 

        bool errorEncountered = false; 

        // return error if the role names are the same
        if (roleAttribute.Role1Name == roleAttribute.Role2Name)
        { 
          SessionData.EdmItemErrors.Add(new EdmItemError(
              System.Data.Entity.Strings.SameRoleNameOnRelationshipAttribute(roleAttribute.RelationshipName, roleAttribute.Role2Name),
                       null)); 
          errorEncountered = true; 
        }


        if (!errorEncountered)
        {
          AssociationType associationType = new AssociationType(
            roleAttribute.RelationshipName, roleAttribute.RelationshipNamespaceName,
            roleAttribute.IsForeignKey, DataSpace.OSpace); 
          SessionData.TypesInLoading.Add(associationType.FullName, associationType);
          TrackClosure(roleAttribute.Role1Type); 
          TrackClosure(roleAttribute.Role2Type); 

          // prevent lifting of loop vars 
          string r1Name = roleAttribute.Role1Name;
          Type r1Type = roleAttribute.Role1Type;
          RelationshipMultiplicity r1Multiplicity = roleAttribute.Role1Multiplicity;
          AddTypeResolver(() => 
            ResolveAssociationEnd(associationType, r1Name, r1Type, r1Multiplicity));

          // prevent lifting of loop vars 
          string r2Name = roleAttribute.Role2Name;
          Type r2Type = roleAttribute.Role2Type; 
          RelationshipMultiplicity r2Multiplicity = roleAttribute.Role2Multiplicity;
          AddTypeResolver(() =>
            ResolveAssociationEnd(associationType, r2Name, r2Type, r2Multiplicity));

          // get assembly entry and add association type to the list of types in the assembly
          Debug.Assert(!CacheEntry.ContainsType(associationType.FullName), "Relationship type must not be present in the list of types"); 
          CacheEntry.TypesInAssembly.Add(associationType); 
        }
      } 
    }

    // ...
  }
}

メソッドで使用される唯一の辞書は ですSessionData.TypesInLoading。キーは と の組み合わせRelationshipNameですRelationshipNamespaceName。面白いことに、コメントには重複したキーをチェックすると書かれていますが、メソッドTryFindNullParametersInRelationshipAttributeは属性のプロパティがnulls でないことだけをチェックします。バグだと思います。

しかし、もっと重要なことは、アセンブリのどこかにとプロパティEdmRelationshipAttributeの組み合わせが同じものが複数あるため、説明されているエラーが発生したに違いないということです。さまざまな理由が考えられます。RelationshipNameRelationshipNamespaceName

  1. EDMX ファイルが正しくありません。
  2. 不適切にコピーされたアセンブリ、
  3. デバッグ構成と同じフォルダーにビルド結果を出力する構成をリリースし、
  4. EF マッピング アセンブリの手動生成のエラー、

残念ながら、壊れた関係の名前を特定することは非常に困難です。おそらくブレークポイントを設定しSystem.Data.Metadata.Edm.ObjectItemAttributeAssemblyLoader.LoadRelationshipTypes()、逆アセンブルでトレースする必要があります。メソッドが何Dictionary.Insertも呼び出されようとしているため、ほとんど不可能だと思います。

それでも解決策が見つからない場合は、問題の再現を準備してここに投稿する必要があります。そうしないと誰も助けてくれません。

于 2012-04-18T15:06:37.790 に答える