.NET 4上的EF4.3.1 - CLR类型到EDM类型的映射是不明确的,因为多个CLR类型与EDM类型匹配

时间:2012-08-24 18:08:37

标签: entity-framework entity-framework-4.3

更新:主题更新 - 现在可以在运行Windows 8的Windows 2012下运行的.NET 4.3上的EF 4.3.1上重现。现在有什么想法会开始发生吗?

受试者说的都是真的。我们刚刚从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,以便在实现后将结果投影到正确的东西。

谢谢, 迪安

2 个答案:

答案 0 :(得分:17)

迪安,

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

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

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

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

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

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

答案 1 :(得分:11)

我想我今天已经触底了。

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