none
EF4 Mapping of CLR type to EDM type is ambiguous error. RRS feed

  • Question

  • I have a single project with multiple models.  Some of the models have entities that are mapped back to the same tables in the store.  (i.e. two models have a Customer entity that is mapped back to the Customer table.)  I am using the Self-Tracking entity templates and each template is in it's own folder with its own namespace and the template code points to the actual edmx file that is in another project.  Those templates are all in a separate assembly from the project that contains the models and the context templates.  The project with the models and contexts has a reference to the assembly containing the generated self-tracking entities.  Everything generates and compiles fine.

    At runtime I get the following error when I try to use one of the generated contexts:

    --------------------------------------

    Schema specified is not valid. Errors:

    The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type 'Customer'. Previously found CLR type 'MyProject.Common.Contracts.Data.OrderManagementModel.Customer', newly found CLR type 'MyProject.Common.Contracts.Data.CustomerManagementModel.Customer.
    -------------------------------------

    Please tell me there is a way to work around this aside from the obvious option of changing the name of one of the entities to be unique or, gasp, putting each model in it's own project.  Hopefully I am missing something.

     

    • Edited by David Totzke Tuesday, September 21, 2010 5:01 PM Remove inaccurate signature.
    Tuesday, September 21, 2010 2:03 PM

Answers

  • @Lingzhi Sun:

    I have discovered that this is a known issue since the beginning of EF.  I'm sorry I don't have a link for you.  I'm not sure if this has been filed as a bug in connect or anywhere.  Daniel Simmons of the EF team can likely confirm this for you.  I'll elaborate more here as in my search I found little out there that describes this exact problem.

    You are correct that the STE classes are in a separate assembly and each tt file is in its own directory so that the generated classes are in a separate namespace from the classes generated for other models.  The same is true for the models in a separate assembly. For example:

    Model structure:

    MyCompany.MyApplication.Server.Data.Customers.CustomerModel.edmx
    MyCompany.MyApplication.Server.Data.Orders.OrderModel.edmx

    Share contract library structure:

    MyCompany.MyApplication.Common.Contracts.Data.Customers.CustomerSte.tt
    MyCompany.MyApplication.Common.Contracts.Data.Orders.OrderSte.tt

    The server-side data assembly has a reference to the shared contract assembly.  I've modified the STE tt code so fix up the reference to the edmx file.  I've also modified the server-side tt files that generate the ObjectContext to include an additional using statement so that they know about the STEs in the share assembly.  As I mentioned, at compile time, everything is happy.

    The problem, as I understand it, is that at runtime when CreateObjectSet<SomeSteType>("SomeSteType") gets called only the type name is used to find the CLR type.  Namespaces are completely ignored.  Even if you changed the code-gen to produce:

    CreateObjectSet<MyCompany.MyApplication.Common.Contracts.Data.Customers.CustomerSte>("CustomerSte")

    The namespace is still ignored.  The upshot of this is that if you have two classes within the same assemble that have the same name, you will get the error in my original post.  The irony of the whole thing is that the error message tells you the FQN of the types it found but can't distinguish between them.  Perhaps there is some technical reason why the namespace is ignored when resolving the types but I can't think of one.  It seems obvious that to be certain you get the right type, you need to use the FQN. 

    The work-around is to simply make sure that every type in the same assembly has a unique name.  Since something like Customer would be common in both the CustomerModel and the OrderModel you can just rename one of them to be Customer1.  At least in Intellisense then you still type Customer and in context you would only see one or the other so it's not too terrible.  It's just messy.

    The other work-around is to separate them into different assemblies.  This is also less than optimal as I have 10 different models and I'm not even done yet. (there are hundreds of tables in the database)

    So there in a nutshell is the problem.  I'd be interested to know if  (a) this is an actual bug being tracked by the EF team, (b) is it on the roadmap for a future update and (c) what time frame for a fix can we expect?

    Thanks for your offer of direct help, I can still send you a small demo solution if you like.  Perhaps you can let me know if you still wish to do that after you check with the EF team?

    Regards,

    Dave Totzke


    David Totzke
    Thursday, September 23, 2010 12:27 PM

All replies

  • Hi,

    Have you used .NET reflector on your assembly? The .edmx's are compiled and embedded in your assembly. Maybe Reflector can provide more insight in what's happened with you mappings inside the assembly.


    If this reply is of help to you, please don't forget to mark it as an answer. Regards, Patriek
    Tuesday, September 21, 2010 2:25 PM
  • Hello,

     

    Welcome to EF forum!

     

    I agree with Patriek that you may use Reflector to check the embedded .edmx.   Also, based on your description, do you mean the model and the STE classes are under different assemblies?   The situation can be complicated.   If it is convenient for you, could you please send me a demo project for further investigation?   You can directly ping me at: v-micsun@microsoft.com.   I will do my best to help.

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, September 22, 2010 2:20 AM
    Moderator
  • @Lingzhi Sun:

    I have discovered that this is a known issue since the beginning of EF.  I'm sorry I don't have a link for you.  I'm not sure if this has been filed as a bug in connect or anywhere.  Daniel Simmons of the EF team can likely confirm this for you.  I'll elaborate more here as in my search I found little out there that describes this exact problem.

    You are correct that the STE classes are in a separate assembly and each tt file is in its own directory so that the generated classes are in a separate namespace from the classes generated for other models.  The same is true for the models in a separate assembly. For example:

    Model structure:

    MyCompany.MyApplication.Server.Data.Customers.CustomerModel.edmx
    MyCompany.MyApplication.Server.Data.Orders.OrderModel.edmx

    Share contract library structure:

    MyCompany.MyApplication.Common.Contracts.Data.Customers.CustomerSte.tt
    MyCompany.MyApplication.Common.Contracts.Data.Orders.OrderSte.tt

    The server-side data assembly has a reference to the shared contract assembly.  I've modified the STE tt code so fix up the reference to the edmx file.  I've also modified the server-side tt files that generate the ObjectContext to include an additional using statement so that they know about the STEs in the share assembly.  As I mentioned, at compile time, everything is happy.

    The problem, as I understand it, is that at runtime when CreateObjectSet<SomeSteType>("SomeSteType") gets called only the type name is used to find the CLR type.  Namespaces are completely ignored.  Even if you changed the code-gen to produce:

    CreateObjectSet<MyCompany.MyApplication.Common.Contracts.Data.Customers.CustomerSte>("CustomerSte")

    The namespace is still ignored.  The upshot of this is that if you have two classes within the same assemble that have the same name, you will get the error in my original post.  The irony of the whole thing is that the error message tells you the FQN of the types it found but can't distinguish between them.  Perhaps there is some technical reason why the namespace is ignored when resolving the types but I can't think of one.  It seems obvious that to be certain you get the right type, you need to use the FQN. 

    The work-around is to simply make sure that every type in the same assembly has a unique name.  Since something like Customer would be common in both the CustomerModel and the OrderModel you can just rename one of them to be Customer1.  At least in Intellisense then you still type Customer and in context you would only see one or the other so it's not too terrible.  It's just messy.

    The other work-around is to separate them into different assemblies.  This is also less than optimal as I have 10 different models and I'm not even done yet. (there are hundreds of tables in the database)

    So there in a nutshell is the problem.  I'd be interested to know if  (a) this is an actual bug being tracked by the EF team, (b) is it on the roadmap for a future update and (c) what time frame for a fix can we expect?

    Thanks for your offer of direct help, I can still send you a small demo solution if you like.  Perhaps you can let me know if you still wish to do that after you check with the EF team?

    Regards,

    Dave Totzke


    David Totzke
    Thursday, September 23, 2010 12:27 PM
  • Hello Dave,

     

    Thank you so much for your detailed post!   J

     

    Yes, I’d like to see the demo project and I will do my best to check the status of this product issue. 

     

    Have a nice weekend!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, September 24, 2010 2:49 AM
    Moderator
  • Hello *,

    This is not a bug if i remember correctly. This was done with an intent. For POCO entity, EF team uses convention to map O space to C space. The convention follows the rule where if a class is found that has the same name and same number of properties as the one defined on the EF model, then the mapping occurs. If there are more then one class found that meets the criteria you get an exception as state above. This was done so that POCO would just simply work for anyone wanting to migrate the their existing poco classes with EF by just building a model. This means that your class can reside in any assembly with whatever namespace and EF would take care of the mapping. Now that kind of flexibility can only be achieved by  doing what they did. This does not mean that you are locked down with the convention Ef chooses. If you want to explicitly specify where EF should find the CLR types for its model, you can use LoadFromAssembly to tell EF to look in this assembly for the CLR types. 

    I doubt this would change..

     


    Zeeshan Hirani Entity Framework 4.0 Recipes by Apress
    http://weblogs.asp.net/zeeshanhirani
    Monday, October 11, 2010 4:54 AM
  • Thanks for the clarification Zeeshan.  At least that makes sense although I don't really agree with the whole convention approach.  POCO in my mind is the edge case here and should not be the driving force for the default behaviour.  As you say, this is unlikely to change.  I have found that as long as I split the types into separate projects, I can have the models alltogether in one project.  I'm using the new T4 templates for self-tracking entities and it works like a champ.  I leave the context with the model and the other gets moved into a separate project for generating the STEs.  It's a compromise that is "good enough" for me.

    Thanks again for the rationale behind this functionality.

     


    Regards, David Totzke
    Monday, December 13, 2010 7:46 PM
  • zeeshan,

    The convention follows the rule where if a class is found that has the same name and same number of properties as the one defined on the EF model, then the mapping occurs.

    Do you happen to know if this has changed in EF 4.1? I have this problem too, and based on my own findings, the convention rule appears to have changed so that if a class is found that has the same name and *includes* the same property names (ignoring their type) as the one defined on the EF model, then the mapping occurs.

    As an example, the following works:

    namespace Entities // EDM types
    {
    	public class Country
    	{
    		public int Id { get; set; }
    		public int Name { get; set; }
    		public string Dummy { get; set; } // doesn't exist in Domain.Country
    	}
    }
    
    namespace Domain // CLR types
    {
    	public class Country
    	{
    		public int Id { get; set; }
    		public int Name { get; set; }
    	}
    }
    
    

    But the following doesn't:

    namespace Entities // EDM types
    {
    	public class Country
    	{
    		public int Id { get; set; }
    		public int Name { get; set; }
    	}
    }
    
    namespace Domain // CLR types
    {
    	public class Country
    	{
    		public int Id { get; set; }
    		public int Name { get; set; }
    		public string Dummy { get; set; } // doesn't exist in Entities.Country
    	}
    }
    
    

    As you can see the number of properties in both types is different in both examples, but the second throws a MetadataException, while the first one works fine.

    Thanks!


    Daniel Liuzzi
    Wednesday, May 11, 2011 3:07 PM
  • If you want to explicitly specify where EF should find the CLR types for its model, you can use LoadFromAssembly to tell EF to look in this assembly for the CLR types. 

    Can someone elaborate on this approach? Anyone got that working?

    I moved my POCO classes to a separate assembly. Right after creating my DbContext, I get the ObjectContext via IObjectContextAdapter and call LoadFromAssembly on that. Still, EF gives me the same error upon first access of a DbSet. It seems it just ignores my LoadFromAssembly call and again searches all available assemblys.

    What I really don't get: On my DbContext I have all my DbSet<> specified, with the exact type which is to be used. If I access one of these DbSets then I want that type to be used. Why does EF have to search here at all? Why not simply use the type I specified on my DbSet? Am I missing something?

    Monday, September 19, 2011 8:56 AM
  • I am very curious as to how to address this issue in my own project as well.  I am trying to map more than one DbContext (which point at db's which share the same views) within the same assembly.  I've divided my objects (POCO's), my context, and configurations by namespace.  I'm dealing with a database first approach, where I've reverse (T4) gen'd my models, dbcontext, configurations, and poco's...we're talking hundreds of tables, in each db...so this is no easy switch around... the overlap in objects (poco's) is caused by shared views (among pre-existing databases) which need to be referenced by each derived DbContext.   I've got about 65 objects which are making my context choke with the following message:

    "The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type"

    I guess based on this thread, I need to separate all my objects and templates into piece part assemblies, but I'm still confused when it comes time to bring it all back together... l too would like to see an example of using the LoadFromAssembly workaround...

    Monday, October 31, 2011 7:13 PM
  • Same, please provide an example if possible.  This issue is causing a major issue in my current design.
    Thursday, December 15, 2011 5:56 PM
  • Unfortunately we get to see more and more MSDN threads lately whose answer was marked as accepted just for the sake of having an answer marked as accepted, not really being helpful.
    • Proposed as answer by whiteheadw Wednesday, October 17, 2012 6:56 PM
    Wednesday, April 4, 2012 8:03 AM
  •  EF5 - the issue is still there. Any suggestions how to bypass it?
    Thursday, October 25, 2012 8:59 PM
  • I use Telerik OpenAccess ORM..not problems here...
    Wednesday, November 21, 2012 2:38 PM
  • There's no excuse for this non-sense.  Lately I'm becoming more and more disenchanted with entity framework.  Namespaces are not a new concept and should never be ignored.  Good grief.
    Thursday, December 27, 2012 11:22 PM
  • I hate to bump old topics but this happened today at work when another developer started his work on our shared enterprise solution.

    We have an assembly with our all POCOs divided by namespace, and another assembly for DataAccess which maps the POCOs to DbContexts. We took a good practice to have every DbContext work with a single namespace of POCOs and in case an object is needed in more than one context, we duplicate it, and if they happen to share a good amount of properties we create a base abstract class for those.

    This worked fine until today, when we had a scenario like Daniel Luzzi described. So far we had, unknowingly, a "type 1" scenario as he describes it, having some entities with same name, different namespaces used in different dbcontexts and no problems at all.

    Today a "type 2" scenario arose, where the new entity had more properties than the "old" one, and the ambigous error gracefully bashed in at our workplace getting everyone crazy for a full 8 hours worktime.

    Now, my biggest question is, why the heck does entity framework scour my assembly for classes? If I tell him "use this" why does it go around and check for other stuff?

    I also tried to create a simple sandbox project with the most basic stuff: 2 classes with the same name in 2 different namespaces. Only ONE DbContext which mapped only ONE of those classes. The other class sat there completely unused, not referenced by anything, not used by anything. And still EF gave that stupid error and the sole fault of that class was that it existed.

    This seems excessively stupid, so that everyone wondered if we were just missing something. We'd really hate to have to change our solution design just to work around a stupid flaw. We don't really want to split our POCOs in a miriad of tiny assemblies just for the sake of this.

    So please if ANYONE has a workaround that does not imply having unique class names (which is totally unacceptable) please share it. I'd love to know if there's a way to tell entity framework to use only what I told it to use and not go around for my assemblies looking for stuff and then throwing exceptions about stuff he should even not know about.

    Thanks.

    Tuesday, February 12, 2013 7:53 PM
  • The only way to make this work is to have conflicting classes defined in separate assemblies.  Yes, it means an extra project or two but it does work just fine.  The irony of your situation, as far as I know, is that this is a "feature" implemented to provide support for POCOs.  The impact of this caused my original issue when you have two edmx files in the same project that map one or more of the same entities.

    And to be honest, your problem is the copy/paste approach to OO design that you have taken.  It it's the same thing, then there should only be one definition of it.  If it's not the same thing, it should have a different name.  Also, having two different implementations of the same abstract base class with the same class name is just asking for trouble.  If a new name isn't appropriate, then it needs to be in a different assembly because it is different.

    I divided my models into separate projects and am happy I did.  In the end it gave me some flexibility I didn't have before.  You might discover the same thing. This isn't going to change as far as I know so I would advise you to just make the split and get on with your life.  There are bigger issues in the world that having an extra assembly or three...

    It's not a very helpful answer I know.  At least you know you aren't alone.  I'm going to ping some EF people I know on Twitter and send them here.  Maybe they will have a better answer for you.

    Cheers.


    Regards, David Totzke

    Wednesday, February 13, 2013 3:04 AM
  • I don't mean to be rude, but the whole reasoning about "if it's the same it should be in one place, if it's not it should have different name, etc" does not hold water. If I were to follow your reasoning, then my obvious question would be: what are namespaces for?

    It's not a copy/paste approach at all. I can have different object domains which share a "concept" but in different domains that concept is just different in its implementation (read: properties and methods) but it is named just the same. I can think of a large number of examples to this.

    So we split them in namespaces, but we don't really want to have separate assemblies for our POCOs. We have, other than pure design reasons, some practical reasons too. Our solution is entirely decoupled, with interfaces representing the various layers, DI through constructor injection and a good IoC (ninject) as glue for everything.

    Our most base assembly (let's call it Common) contains all the abstractions, as well as configuration utilities, extension methods and so forth. It also contains our POCOs divided in namespaces, like Common.Poco.MyDomain1, Common.Poco.MyDomain2, etc.

    You can see the big problem, if I were to put my objects in an assembly called "Common.Poco" I would just be asking for circular reference, as Common.Poco would need to reference "Common" for utilities, extension methods and other stuff, but "Common" should reference "Common.Poco" as well because abstractions will contain definition of methods that need to return my POCOs. And you know too well that circular references are one of the incarnations of pure evil which cause sadness, global warming, death & decay and despair all over the world.

    But I digress. I don't really think that having the same class in different namespaces but same assembly is a design flaw at all. That's what namespaces are for, besides giving clean separation of concepts and more structure to our classes.

    Lastly, other ORMs don't have any problem with this, like NHibernate just to name one of the most popular. I just plain love EF for its neat features (Code First and Migrations above all) but I really hate this stupid effect which has no real use, at least to what I see. It should limit itself to what you tell it to use.

    Thursday, February 14, 2013 8:59 PM
  • We are trying to keep in practice a "separation of concerns" between our data model and our domain model, and thus our data layer and domain layer.  As such, we have separate projects and therefore separate assemblies where a "Customer" class exists - one generated by the EF with a T4 template, and the other hand rolled in our domain layer project that doesn't involve EF, and has different/additional properties and methods where our business logic resides.

    Regardless, we are getting this error with EF5.  So, it seems the problem has only gotten worse.  You can no longer have different classes with the same name in different assemblies and under different namespaces as long as both assemblies are loaded into the same app domain and one of those class names in used by EF.

    I can't believe Microsoft would make such a design decision and ignore the outcry...

    Friday, March 8, 2013 5:46 PM
  • Just add the EntityFramework as "Code First from database" and not as "EF Designer from database". This resolved my problem, but it has a dark side, if you change your database you have to remove all the classes and add it again, or just edit the classes, I use the last when I change properties of the columns, like "Allows null" or the size of a string. But if you add columns I recomend remove and add again the classes.
    Monday, August 13, 2018 5:03 PM