The mapping of CLR type to EDM type is ambiguous with EF 6 & 5?
Asked Answered
R

16

87

Please any one can help me to fix this error?

Schema specified is not valid. Errors:

The mapping of CLR type to EDM type is ambiguous because multiple CLR types match the EDM type 'City_DAL'. Previously found CLR type 'CeossDAL.City_DAL', newly found CLR type 'CeossBLL.City_DAL'.

The main problem that I have DAL and this contains the EF and BLL and this contains the same classes of the DAL but differ in the namespace and this is what cause the problem

I can't know how to get rid of these problem, can you please help me?

Also I will be appreciated if some one give me sample to use n-tier architecture with EF

Thank you

Ricotta answered 17/2, 2013 at 23:30 Comment(0)
L
79

Don't use classes with the same unqualified name - EF uses only class names to identify the type mapped in EDMX (namespaces are ignored) - it is a convention to allow mapping classes from different namespaces to single model. The solution for your problem is to name your classes in BLL differently.

Lacy answered 18/2, 2013 at 19:37 Comment(10)
If I name the classes in BLL differently how can EF map between my classess in the DAL and BLL ?Ricotta
EF does not map between two classes. It maps between entity in the diagram and looks for a single class with the same name.Lacy
Ok , I work with code first model , now if I made a class in the BLL with the name of Product_BLL and I have the same class in the DAL with EF and its name is Product_DAL,now when I want to add an entity with this class to the database , EF will wait from me to pass an object from Product_DAL class not Product_BLL ? is that right or i had misunderstand ? thanks alot for ur helpRicotta
Why do you have two classes? You should have only one.Lacy
I have two classes as I work with a project with 3-tier (DAL/BLL/PL) ,so I have the EF in the DAL and I have the same EF classes in the BLL ,in the BLL each class contains methods that used to call methods from DAL and these methods in the DAL need such as an object from class Product that exists in the DAL but I call these methods from the BLL ,so when I pass that object to DAL methods I create an object from the Product that exists in the BLL and here the exception is raised.Ricotta
@Ladislav I would have given up on EF without your SO posts. Saved again. Thank you.Hypochondria
EF collision happens only when two classes have the same name AND the same set of parameters.Vernissage
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.Rodie
Adding multiple classes with the same name should be okay as long as they are located in different physical layers. For example, you could have a class named Product, which exists in the repository layer, the domain and the presentation layer. You would just some mapping framework to move your data from layer to layer. EF will not care what you name your classes in this case.Carmeliacarmelina
Ignoring the namespace of the class is a known bug in Entity Framework and is not expected to be fixed any time soon. Renaming the entity is another workaround that will also disambiguate the class names.Laodicea
F
50

Workaround: Change a property on one of the two identical classes.

EF matches on class name AND class properties. So I just changed a property name on one of the EF objects, and the error is gone.

As @Entrodus commented on one of the other answers:

EF collision happens only when two classes have the same name AND the same set of parameters.

Featherstone answered 16/10, 2015 at 16:27 Comment(6)
For my money, this is the best answer - I'd rather mess with a property name than a class nameDreher
I just put them in different assemblies.. no need to mess with thisAlgicide
@ErikBergstedt If you use both assemblies in the same solution, you'll start getting the error.Railway
In the conflicting Entity in the EDMX, i tried changing the name of one of the properties, adding another property, adding a Partial class with more "dummy" properties... Neither of them worked. Only changing the Entity's name worked for me...Unplug
That's a meaningless statement. Classes don't have parameters.Laodicea
Removing nullable properties also does not appear to be a solution. I prefer to pick a property that is not used in one of the context, naming it DONOTUSE1 etc. and making it private. It's ugly, but works. You may even want to add a useless bit column for this purposeParthenia
D
11

This MSDN forum question might be helpful. It suggest placing the BLL and DAL classes in separate assemblies.

Discrepant answered 6/3, 2013 at 8:47 Comment(2)
If you use both assemblies in the same solution, the error will occur... I have the exact same problem. Both are different database but have the same tblSetting. I put it on 2 different assemblies (always put on different assembly) and it doesn't work :(Mischiefmaker
i used both assemblies in the same solution and error didnt show up so i dont know whats going on with this comment...Conlee
O
9

For EF 6.x, I found some notes at https://github.com/aspnet/EntityFramework/issues/941 and fixed this in my solution by adding annotation to the EDM type.

I edited the EDMX file manually and changed a line like this:

<EntityType Name="CartItem">

to this:

<EntityType Name="CartItem" customannotation:ClrType="EntityModel.CartItem">

or use this if you have existing type elsewhere:

<EntityType Name="CartItem" customannotation:ClrType="MyApp.CartItem, MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">

where EntityModel is the namespace used for my EF model, and MyApp is the namespace of a business object

Officiate answered 5/7, 2017 at 16:16 Comment(4)
This did not work for me (tried EF 6.0 and 6.3), working with SQLite databaseManrope
:-( I only used it with MSSQLOfficiate
That Github post also says to add customannotation:UseClrTypes to <EntityContainer>. (Still didn't work for me in EF 6)Kenosis
It does work for me with MSSQL and EF 6.3.0 (haven't tested other combinations).Radices
K
8

In some cases this is more of a symptom than the actual problem. For me, it usually pops up when I try to call a function inside a Linq query without calling .ToList() first.

E.g. the error that brought me here was caused because I did this:

var vehicles = DB.Vehicles.Select(x => new QuickSearchResult()
{
    BodyText = x.Make + " " + x.Model + "<br/>"
    + "VIN: " + x.VIN + "<br/>"
    + "Reg: " + x.RegistrationNumber +"<br/>"
    + x.AdditionalInfo
    type = QuickSearchResultType.Vehicle,//HERE. Can't use an enum in an IQueryable.
    UniqueId = x.VehicleID
});

I had to call .ToList(), then iterate through each item and assign the type to it.

Keneth answered 8/2, 2017 at 9:29 Comment(1)
Thank you! This was exactly my issue, casting to an enum within the linq statement.Orthohydrogen
N
2

I got the error above because for both connection strings, I had the same value for metadata specified in my main project's config file, like below:

<add name="EntitiesA" connectionString="metadata=res://*/EntitiesA.csdl|res://*/EntitiesA.ssdl|res://*/EntitiesA.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=localhost;initial catalog=MyDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

<add name="EntitiesB" connectionString="metadata=res://*/EntitiesA.csdl|res://*/EntitiesA.ssdl|res://*/EntitiesA.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=localhost;initial catalog=MyDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

I ended up copying the correct connection string from the EntitiesB's project's config file.

Nagel answered 2/2, 2018 at 4:46 Comment(2)
I think the OP has the problem with the name entity name. I did too... I did put the correct connection string in my Web.config. It still doesn't work :(Mischiefmaker
Fixed the issue after seeing your answer and spending 3 hours figuring out.Epsilon
H
1

This may not have been available when the question was asked, but another solution is to delete the EDMX and recreate it as a code-first entity data model. In EF6, with code-first, you can map two classes with the same name from different model namespaces without creating a conflict.

To create the entity data model in Visual Studio (2013), go to "Add" > "New Item..." > "ADO.NET Entity Data Model". Be sure to choose the "Code First from database" option.

Highfalutin answered 31/1, 2017 at 23:4 Comment(4)
This did not work for me (tried EF 6.0 and 6.3), working with SQLite databaseManrope
I don't know whether it makes a difference, but I was on MS SQL Server when I did this.Highfalutin
This absolutely works for me. I have a situation where none of the other solutions seem to apply.Vaticinal
That's because the entity types are annotated differently for Code First. See @Ekus's answer at https://mcmap.net/q/237893/-the-mapping-of-clr-type-to-edm-type-is-ambiguous-with-ef-6-amp-5.Laodicea
S
0

Another reason you might get this error: If you're loading custom assemblies with Assembly.LoadFile that have edmx files, that have already been loaded into memory. This creates duplicate classes that entity framework doesn't like.

Stravinsky answered 21/12, 2017 at 21:2 Comment(0)
J
0

For me this was because I was attempting to access a type with the same name on the wrong context instance.

Say both ContextA and ContextB have SomeType. I was trying to access ContextA.SomeType on an instance of ContextB.

Judges answered 13/5, 2018 at 17:19 Comment(0)
S
0

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.

Selfindulgent answered 13/8, 2018 at 16:53 Comment(0)
D
0

I was able to solve this issue without renaming the classes, properties, or metadata.

I had my project setup with a T4 transform creating entity objects in a DAL project, and a T4 transform creating domain objects in a Domain project, both referencing the EDMX to generate identical objects, and then I was mapping the DAL objects to the Domain objects.

The error only occurred when I was referencing other classes (enums in my case) from the Domain assembly in my queries. When I removed them, the error went away. It looks like EF was loading up my Domain assembly because of this, seeing the other identically named classes, and blowing up.

To resolve this, I made a separate assembly that only contained my T4 transformed Domain classes. Since I never need to use these inside a query (only after the query to map to), I no longer have this issue. This seems cleaner and easier than the answers below.

Discourtesy answered 2/10, 2018 at 17:29 Comment(0)
P
0

if you have 2 connection string in web config but you want to use one connection string You use dynamic create connection string other entities. I have edmx(db first) and code first Entities in my solution. I use this class in Code first entities.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity.Core.EntityClient;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data
{
    public class SingleConnection
    {
        private SingleConnection() { }
        private static SingleConnection _ConsString = null;
        private String _String = null;

        public static string ConString
        {
            get
            {
                if (_ConsString == null)
                {
                    _ConsString = new SingleConnection { _String = SingleConnection.Connect() };
                    return _ConsString._String;
                }
                else
                    return _ConsString._String;
            }
        }

        public static string Connect()
        {
            string conString = ConfigurationManager.ConnectionStrings["YourConnectionStringsName"].ConnectionString;

            if (conString.ToLower().StartsWith("metadata="))
            {
                System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder efBuilder = new System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder(conString);
                conString = efBuilder.ProviderConnectionString;
            }

            SqlConnectionStringBuilder cns = new SqlConnectionStringBuilder(conString);
            string dataSource = cns.DataSource;
            SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
            {
                DataSource = cns.DataSource, // Server name
                InitialCatalog = cns.InitialCatalog,  //Database
                UserID = cns.UserID,         //Username
                Password = cns.Password,  //Password,
                MultipleActiveResultSets = true,
                ApplicationName = "EntityFramework",

            };
            //Build an Entity Framework connection string
            EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
            {
                Provider = "System.Data.SqlClient",
                Metadata = "res://*",
                ProviderConnectionString = sqlString.ToString()
            };
            return entityString.ConnectionString;
        }
    }
}

And when I call entities

private static DBEntities context
{
get
{
    if (_context == null)
        _context = new DBEntities(SingleConnection.ConString);

    return _context;

}
set { _context = value; }
}
Politian answered 13/12, 2018 at 9:54 Comment(0)
G
0

I Think u Have a Class X named "MyClass" in Entity Models and Another Class Called "MyClass" in the same WorkFolder or Extended of the first Class. That is my problem and i fix it.

Gunnar answered 1/2, 2019 at 12:53 Comment(0)
T
0

I found that using the custom annotation solution works with EF 6.2.0. Just make sure to change in the ConceptualModels node and use full namespace for the type.

<edmx:ConceptualModels>
  <Schema Namespace="Sample.Access.Data.Ef" Alias="Self" annotation:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
    <EntityType Name="DbTableName" customannotation:ClrType="Sample.Access.Data.Ef.DbTableName, Sample.Access.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
      <Key>
        <PropertyRef Name="DbTableNameId" />
      </Key>
      <Property Name="DbTableNameId" Type="Int32" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
      <Property Name="OptionName" Type="String" MaxLength="100" FixedLength="false" Unicode="false" Nullable="false" />
      <Property Name="Value" Type="String" MaxLength="500" FixedLength="false" Unicode="false" Nullable="false" />
      <Property Name="UpdatedDate" Type="DateTime" Nullable="false" Precision="3" />
    </EntityType>
    <EntityContainer Name="MyEntities" annotation:LazyLoadingEnabled="true" customannotation:UseClrTypes="true">
      <EntitySet Name="DbTableNames" EntityType="Self.DbTableName" />
    </EntityContainer>
  </Schema>
</edmx:ConceptualModels>
Throe answered 10/8, 2021 at 15:58 Comment(0)
D
0

Open Model Browser and just rename Tables ona by one. After that update table names on your code.

Deviate answered 28/6, 2023 at 21:45 Comment(0)
A
-9

There is a library called AutoMapper which you can download. It helps you to define class mappings from one type to another.

Mapper.CreateMap<Model.FileHistoryEFModel, DataTypes.FileHistory>();
Mapper.CreateMap<DataTypes.FileHistory, Model.FileHistoryEFModel>();
Annotate answered 9/2, 2015 at 12:7 Comment(1)
not really applicable to the users question. Using automapper isn't going to just fix his issue.Eschalot

© 2022 - 2024 — McMap. All rights reserved.