19

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?

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>().Select(a => new DTO.A { Id = a.Id, Name = a.Name }).ToArray();

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'.

Stack trace is

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)

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?

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.

Thanks, Dean

2
  • 1
    Just to give you an update on that - we are considering a fix for this in one of the future updates where would not thrown for v1 or v2 schemas. Similarly on EF6 we would not try loading the referenced assembly if schema is v1 or v2 since there is no need for it and it is costly. Just for reference the bug we are using to track this for EF6 - entityframework.codeplex.com/workitem/596 (I think you are familiar with this one ;)
    – Pawel
    Commented Dec 19, 2012 at 16:46
  • Thanks Pawel. In this particular project we're actually upgrading to .NET 4.5 so we've put in place other workarounds, however this will definitely help us in other places were we aren't upgrading to 4.5 in the near future!
    – Dean Ward
    Commented Dec 19, 2012 at 19:38

2 Answers 2

18

Dean,

This is a known issue as reported in the following links:

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

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

The namespace is ignored by the Entity Framework so the same tables in multiple databases cause the problem because the Entity Framework only looks at the table name.

Apparently, the Entity Framework team doesn't understand the importance of supporting whatever database schema customers have. They also have lost sight of the fact that clean compiling code should also run.

If you look at the links I mentioned above, you will see that correcting their errors have a low priority. I don't know about you but I'd be fired over that attitude.

6
  • 8
    Entity Framework is open source. Feel free to contribute fixes to these bugs.
    – Pawel
    Commented Apr 4, 2013 at 22:15
  • @Pawel Will your team consider using someone elses contribution as part of your updates? Commented Oct 3, 2013 at 22:13
  • @LéMuffinMan - yes, EF accepts contributions from the community. In EF6 alone we had more than 20 contributions. Take a look at the blog post announcing EF6 RC1 - blogs.msdn.com/b/adonet/archive/2013/08/21/…. In the section "What Else is New in EF6" you can find names of people who contributed to EF6. For more details see "Contribute" section here entityframework.codeplex.com and entityframework.codeplex.com/wikipage?title=Contributing
    – Pawel
    Commented Oct 3, 2013 at 23:40
  • 2016 and still a problem. I am working with two pre-existing databases and theres no way I can change them
    – rdans
    Commented Jun 28, 2016 at 14:36
  • 3
    Obviously a low priority, I am still having the same issue in 2019 EF6.
    – joedotnot
    Commented Feb 20, 2019 at 1:29
11

I think I got to the bottom of it today.

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.

4
  • Thank goodness I'm not the only one: I have two entities in project-1 and two models (classes) in project-2 that correspond to the entities in project-1 (same name and similar properties). i have a 3rd class in project-2 that does not have a corresponding entity, but two of the properties are enums (enums also located in project-2). when I create a new instance of this 3rd model while I'm in the entity framework context, I get the ambiguous CLF-EDM error message. If I create a new instance without using the enums, no error message.
    – YeeHaw1234
    Commented Jan 15, 2014 at 20:12
  • in a hurry, i added multiple .edmx file which had same class names in my MVC Project and thus wasted time figuring this error , hope helps some one.
    – Shaiju T
    Commented Sep 16, 2015 at 11:09
  • 1
    little remark : this problem doesn't appear with entity framework code first
    – Proviste
    Commented Jan 5, 2016 at 17:18
  • So, just make sure your entities aren't named the same as the models.
    – Jnr
    Commented Dec 19, 2020 at 7:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.