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

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

问题描述:

更新:主题已更新 - 现在可以在EF 4.3.1下重新运行.NET 4,运行VS2012,Windows 8下安装。任何想法为什么会这样开始发生?

Update: Subject updated - this is now reproducible on EF 4.3.1 under .NET 4 running with VS2012 installed under Windows 8. Any ideas why this would start happening now?

主题真的很好。我们刚从EF 4.3代码升级到在.NET 4.0下运行的EF 5。我们有一个查询类似于以下内容:

The subject says it all really. We just upgraded from EF 4.3 code-first to EF 5 running under .NET 4.0. We have a query that looks similar to the following:

ctx.Set< Entities.A>()。选择(a => DTO.A {Id = a.Id,Name = a.Name})ToArray();

Entities.A 在一个名为 Entities DTO.A 的程序集中定义一个名为 DTO 的程序集。在EF 4.3中,这样做不错,但在EF 5.0下,它会抛出以下异常:

Entities.A is defined in an assembly called Entities and DTO.A is defined in an assembly called DTO. In EF 4.3 this worked fine, but under EF 5.0 it throws the following exception:

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,它不能消除歧义只使用实体名称),而是从不同的大会?

I'd understand the problem if the types were in the same assembly (a long documented issue with EF whereby it cannot disambiguate using just the entity name), but from a different assembly?

任何想法从哪里去?我看不到任何告诉EF有效地忽视DTO程序集的方法,我猜测查询表达式生成需要知道DTO才能将结果投影到正确的物化实体上。

Any ideas where to go from here? I can't see any way of telling EF to effectively disregard the DTO assembly and I'm guessing query expression generation requires knowledge of the DTO in order to project the results into the right thing upon materialization.

谢谢,
Dean

Thanks, Dean

我想我今天到底了。

对我来说,枚举类型生活在一个单独的程序集中,并且转换触发器从此程序集加载类型。此程序集包含与Entities.A类型匹配的类型DTO.A。这导致歧义,反过来又会引起异常。请注意,.NET Framework 4中没有发生,因为EF4中的枚举类型不受支持,并且转换操作不会导致来自其他程序集的加载类型,因此针对.NET Framework 4的项目是.NET Framework 4.5中的回归。
在EF6中,无论.NET Framework版本如何,我们将永远抛出它们的行为。

It looks to me that the enum type lives in a separate assembly and the cast triggers loading types from this assembly. This assembly happens to contain the type 'DTO.A' which matches the 'Entities.A' type. This cause the ambiguity which in turn causes an exception to be thrown. Note that did not happen in .NET Framework 4 since enum types in EF4 were not supported and cast operation did not cause loading types from the other assembly so for projects targeting .NET Framework 4 this is a regression in .NET Framework 4.5. In EF6 the behavior will be the same regardless of .NET Framework version - we will always throw.