【问题标题】:EF4.3.1 on .NET 4 - The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type.NET 4 上的 EF4.3.1 - CLR 类型到 EDM 类型的映射不明确,因为多个 CLR 类型与 EDM 类型匹配
【发布时间】:2012-08-24 18:08:37
【问题描述】:

更新:主题已更新 - 现在可以在 .NET 4 下的 EF 4.3.1 上重现,并在 Windows 8 下安装 VS2012。知道为什么现在会开始发生这种情况吗?

主题说明了一切。我们刚刚从 EF 4.3 代码优先升级到在 .NET 4.0 下运行的 EF 5。我们有一个类似于以下内容的查询:

ctx.Set<Entities.A>().Select(a => new DTO.A { Id = a.Id, Name = a.Name }).ToArray();

Entities.A 在名为Entities 的程序集中定义,DTO.A 在名为DTO 的程序集中定义。在 EF 4.3 中这工作正常,但在 EF 5.0 下它会引发以下异常:

Schema specified is not valid. Errors: 
The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type 'A'. Previously found CLR type 'Entities.A', newly found CLR type 'DTO.A'.

堆栈跟踪是

at System.Data.Metadata.Edm.ObjectItemCollection.LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly, Boolean loadReferencedAssemblies, EdmItemCollection edmItemCollection, Action'1 logLoadMessage)
at System.Data.Metadata.Edm.ObjectItemCollection.ImplicitLoadAssemblyForType(Type type, EdmItemCollection edmItemCollection)
at System.Data.Metadata.Edm.MetadataWorkspace.ImplicitLoadAssemblyForType(Type type, Assembly callingAssembly)
at System.Data.Objects.ELinq.ExpressionConverter.TryGetValueLayerType(Type linqType, TypeUsage& type)
at System.Data.Objects.ELinq.ExpressionConverter.GetCastTargetType(TypeUsage fromType, Type toClrType, Type fromClrType, Boolean preserveCastForDateTime)
at System.Data.Objects.ELinq.ExpressionConverter.CreateCastExpression(DbExpression source, Type toClrType, Type fromClrType)
at System.Data.Objects.ELinq.ExpressionConverter.ConvertTranslator.TranslateUnary(ExpressionConverter parent, UnaryExpression unary, DbExpression operand)
at System.Data.Objects.ELinq.ExpressionConverter.UnaryTranslator.TypedTranslate(ExpressionConverter parent, UnaryExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.UnaryTranslator.TypedTranslate(ExpressionConverter parent, UnaryExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateSet(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.Convert()
at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)

如果类型在同一个程序集中,我会理解问题(一个长期记录的 EF 问题,它不能仅使用实体名称来消除歧义),但来自不同的程序集?

有什么想法可以从这里开始吗?我看不出有任何方法可以告诉 EF 有效地忽略 DTO 程序集,而且我猜查询表达式生成需要了解 DTO,以便在实现时将结果投影到正确的东西中。

谢谢, 院长

【问题讨论】:

  • 只是为了给你一个更新 - 我们正在考虑在未来的更新之一中解决这个问题,其中不会为 v1 或 v2 模式抛出。同样,在 EF6 上,如果架构是 v1 或 v2,我们不会尝试加载引用的程序集,因为不需要它而且成本很高。仅供参考,我们用于跟踪 EF6 的错误 - entityframework.codeplex.com/workitem/596(我认为您对此很熟悉;)
  • 谢谢帕维尔。在这个特定的项目中,我们实际上正在升级到 .NET 4.5,因此我们已经制定了其他解决方法,但是如果我们在不久的将来不升级到 4.5,这肯定会对我们在其他地方有所帮助!

标签: entity-framework entity-framework-4.3


【解决方案1】:

院长,

这是以下链接中报告的已知问题:

http://entityframework.codeplex.com/workitem/483

http://entityframework.codeplex.com/workitem/589

命名空间被实体框架忽略,因此多个数据库中的相同表会导致问题,因为实体框架只查看表名。

显然,实体框架团队不了解支持客户拥有的任何数据库架构的重要性。他们也忽略了干净的编译代码也应该运行这一事实。

如果您查看我上面提到的链接,您会发现纠正错误的优先级很低。我不了解你,但我会因为这种态度而被解雇。

【讨论】:

  • 实体框架是开源的。随意贡献修复这些错误。
  • @Pawel 您的团队是否会考虑使用其他人的贡献作为更新的一部分?
  • @LéMuffinMan - 是的,EF 接受来自社区的贡献。仅在 EF6 中,我们就有 20 多个贡献。查看宣布 EF6 RC1 - blogs.msdn.com/b/adonet/archive/2013/08/21/… 的博文。在“EF6 中的其他新增功能”部分中,您可以找到为 EF6 做出贡献的人员的姓名。有关更多详细信息,请参阅此处的“贡献”部分 entityframework.codeplex.comentityframework.codeplex.com/wikipage?title=Contributing
  • 2016 仍然是一个问题。我正在使用两个预先存在的数据库,我无法更改它们
  • 显然是低优先级,我在 2019 EF6 中仍然遇到同样的问题。
【解决方案2】:

我想我今天已经弄明白了。

在我看来,枚举类型存在于单独的程序集中,并且强制转换触发了从该程序集中加载类型。该程序集恰好包含与“Entities.A”类型匹配的“DTO.A”类型。这会导致歧义,进而导致引发异常。请注意,在 .NET Framework 4 中没有发生这种情况,因为不支持 EF4 中的枚举类型,并且强制转换操作不会导致从其他程序集加载类型,因此对于面向 .NET Framework 4 的项目,这是 .NET Framework 4.5 中的回归。 在 EF6 中,无论 .NET Framework 版本如何,行为都是相同的——我们总是会抛出异常。

【讨论】:

  • 谢天谢地,我不是唯一一个:我在 project-1 中有两个实体,在 project-2 中有两个模型(类)对应于 project-1 中的实体(同名和相似特性)。我在 project-2 中有一个没有相应实体的第三类,但其中两个属性是枚举(枚举也位于 project-2 中)。当我在实体框架上下文中创建此第 3 个模型的新实例时,我收到了模棱两可的 CLF-EDM 错误消息。如果我在不使用枚举的情况下创建新实例,则不会出现错误消息。
  • 匆忙中,我在我的 MVC 项目中添加了具有相同类名的 multiple .edmx 文件,因此浪费了时间来解决这个错误,希望对某人有所帮助。
  • 小备注:实体框架代码先不会出现这个问题
  • 所以,只要确保您的实体与模型的名称不同。
猜你喜欢
  • 2015-01-15
  • 1970-01-01
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 2015-04-11
  • 1970-01-01
  • 2014-07-31
相关资源
最近更新 更多