已添加具有相同密钥的项目 - 仅处于发布模式
Posted
技术标签:
【中文标题】已添加具有相同密钥的项目 - 仅处于发布模式【英文标题】:An item with the same key has already been added - Just in Release mode 【发布时间】:2012-04-18 09:11:57 【问题描述】:专家,
我在运行时第一次使用实体框架函数时遇到此 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)
【问题讨论】:
您使用哪个版本和风格(POCO、Code First 等)的 EF? 堆栈跟踪中应该有更多信息。你可能剪过什么吗? 刚刚从现有的 mssql 数据库创建了一个模型。没有 poco。 代码和环境怎么样?当您执行 dbug 版本时,是否在相同的环境中(用户数量等)?是网页版还是桌面版? 看起来像一个错误。也许你应该在连接网站上发布一个重现。它仍然可以在某种程度上与 edmx 和映射相关,因为 ExecuteStoreQuery 使用映射来具体化查询结果。 【参考方案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
只检查属性的属性不是null
s。我想这是一个错误。
但更重要的是,所描述的错误一定是发生了,因为在您的程序集中的某个地方,您有多个EdmRelationshipAttribute
具有相同的RelationshipName
和RelationshipNamespaceName
属性组合。可能有多种原因:
-
EDMX 文件不正确。
不正确地复制程序集,
发布配置,将其构建结果输出到与调试配置相同的文件夹中,
手动生成 EF 映射程序集时出错,
等
不幸的是,要找到破裂关系的名字将非常困难。您可能必须在System.Data.Metadata.Edm.ObjectItemAttributeAssemblyLoader.LoadRelationshipTypes()
处设置断点并在反汇编中跟踪它。我想说这几乎是不可能的,因为 Dictionary.Insert
方法将被调用很多次次。
如果所有这些仍然不能提供解决方案,那么您确实需要准备一份您的问题的副本并将其发布在此处。否则没人能帮上忙。
【讨论】:
感谢您的回答。昨天晚上,我发现 ExecuteStoreQuery 导致异常。不知道为什么。所以 edmx 或程序集完全没有问题.. :/以上是关于已添加具有相同密钥的项目 - 仅处于发布模式的主要内容,如果未能解决你的问题,请参考以下文章
Windows Azure:“已添加具有相同密钥的项目。”选择时抛出异常
Ionic.Zip ArgumentException(已添加具有相同密钥的项目)