We're using EF 4.3.1 code-first under .NET 4.0 and VS2012. We have a query that looks similar to the following:<br /><br />ctx.Set<Entities.A>().Select(a => new DTO.A { Id = a.Id, Name = a.Name }).ToArray();<br /><br />Entities.A is defined in an assembly called Entities and DTO.A is defined in an assembly called DTO. Under VS2010 EF 4.3 this worked fine, but under EF 5.0 it throws the following exception:<br /><br />Schema specified is not valid. Errors: <br />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'.<br /><br />Stack trace is<br /><br />at System.Data.Metadata.Edm.ObjectItemCollection.LoadAssemblyFromCache(ObjectItemCollection objectItemCollection, Assembly assembly, Boolean loadReferencedAssemblies, EdmItemCollection edmItemCollection, Action'1 logLoadMessage)<br />at System.Data.Metadata.Edm.ObjectItemCollection.ImplicitLoadAssemblyForType(Type type, EdmItemCollection edmItemCollection)<br />at System.Data.Metadata.Edm.MetadataWorkspace.ImplicitLoadAssemblyForType(Type type, Assembly callingAssembly)<br />at System.Data.Objects.ELinq.ExpressionConverter.TryGetValueLayerType(Type linqType, TypeUsage& type)<br />at System.Data.Objects.ELinq.ExpressionConverter.GetCastTargetType(TypeUsage fromType, Type toClrType, Type fromClrType, Boolean preserveCastForDateTime)<br />at System.Data.Objects.ELinq.ExpressionConverter.CreateCastExpression(DbExpression source, Type toClrType, Type fromClrType)<br />at System.Data.Objects.ELinq.ExpressionConverter.ConvertTranslator.TranslateUnary(ExpressionConverter parent, UnaryExpression unary, DbExpression operand)<br />at System.Data.Objects.ELinq.ExpressionConverter.UnaryTranslator.TypedTranslate(ExpressionConverter parent, UnaryExpression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.UnaryTranslator.TypedTranslate(ExpressionConverter parent, UnaryExpression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateSet(Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)<br />at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)<br />at System.Data.Objects.ELinq.ExpressionConverter.Convert()<br />at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)<br />at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)<br /><br />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?<br /><br />Is this a regression, it used to work...?
Comments: This is also a perf regression. If someone is using EF6 with v1 or v2 schemas we should not try loading types from external assemblies when seeing an enum type since enum types were introduced in v3. Loading types is generally expensive so we should short-circuit this for v1 and v2 schemas. I believe the fix for this would be in ExpressionConverter.TryGetValueLayerType . I think we can do more something like this: // Determine C-Space equivalent type for linqType private bool TryGetValueLayerType(Type linqType, out TypeUsage type) { // Remove nullable Type nonNullableType = TypeSystem.GetNonNullableType(linqType); // strip enums for v1 and v2 schemas If (nonNullableType.IsEnum && schemaversion < v3) { nonNullableType = nonNullableType.GetEnumUnderlyingType() }
Comments: This is also a perf regression. If someone is using EF6 with v1 or v2 schemas we should not try loading types from external assemblies when seeing an enum type since enum types were introduced in v3. Loading types is generally expensive so we should short-circuit this for v1 and v2 schemas. I believe the fix for this would be in ExpressionConverter.TryGetValueLayerType . I think we can do more something like this: // Determine C-Space equivalent type for linqType private bool TryGetValueLayerType(Type linqType, out TypeUsage type) { // Remove nullable Type nonNullableType = TypeSystem.GetNonNullableType(linqType); // strip enums for v1 and v2 schemas If (nonNullableType.IsEnum && schemaversion < v3) { nonNullableType = nonNullableType.GetEnumUnderlyingType() }