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

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

91480 次浏览

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.

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

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>();

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.

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.

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.

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

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.

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.

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.

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.

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.

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; }
}

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.

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>