CLR类型到EDM类型的映射在EF 6和5中不明确?


75

请任何人可以帮助我解决此错误?

指定的架构无效。错误:

CLR类型到EDM类型的映射不明确,因为多个CLR类型与EDM类型“ City_DAL”匹配。先前找到的CLR类型为“ CeossDAL.City_DAL”,新近发现的CLR类型为“ CeossBLL.City_DAL”。

我有DAL的主要问题,它包含EF和BLL,并且包含DAL的相同类,但名称空间不同,这是导致问题的原因

我不知道该如何解决这些问题,请您能帮帮我吗?

如果有人给我示例以在EF中使用n层架构,我也将不胜感激

谢谢

Answers:


78

不要使用具有相同非限定名称的类-EF仅使用类名称来标识EDMX中映射的类型(忽略名称空间)-这是一种约定,允许将类从不同的名称空间映射到单个模型。解决您的问题的方法是在BLL中以不同的方式命名您的类。


如果我以不同的方式命名BLL中的类,那么EF如何在DAL和BLL中的类之间映射?
Mahmoud Samir

1
EF不在两个类之间映射。它在图中的实体之间进行映射,并查找具有相同名称的单个类。
Ladislav Mrnka

3
我在使用三层(DAL / BLL / PL)的项目时有两个类,所以我在DAL中有EF,而在BLL中我有相同的EF类,在BLL中,每个类都包含使用的方法调用DAL中的方法以及DAL中的这些方法,例如DAL中存在的Product类中的对象,但是我从BLL调用了这些方法,因此,当我将该对象传递给DAL方法时,我会从Product中创建一个对象在BLL中存在,并且在这里引发了异常。
Mahmoud Samir

4
@Ladislav如果没有您的SO职位,我本该放弃EF。再次保存。谢谢。
尼尔·汤普森

9
仅当两个类具有相同的名称和相同的参数集时,才会发生EF冲突。
Nikos Tsokos 2014年

41

解决方法:更改两个相同类之一的属性。

EF在类名和类属性上匹配。因此,我只是更改了EF对象之一的属性名称,错误消失了。

当@Entrodus评论其他答案之一时:

仅当两个类具有相同的名称和相同的参数集时,才会发生EF冲突。


7
为了我的钱,这是最好的答案-我宁愿搞乱属性名称而不是类名称
OutstandingBill

2
我只是将它们放在不同的组件中。.无需对此
烦恼

6
@ErikBergstedt如果在同一解决方案中同时使用两个程序集,则将开始出现错误。
Tundey

4
在EDMX中冲突的Entity中,我尝试更改其中一个属性的名称,添加另一个属性,添加具有更多“虚拟”属性的Partial类……它们都不起作用。仅更改实体名称对我
有用

3
那是毫无意义的声明。类没有参数。
Suncat2000

11

这个MSDN论坛问题可能会有所帮助。建议将BLL和DAL类放在单独的程序集中。


2
如果您在同一解决方案中使用两个程序集,则会发生错误...我有完全相同的问题。两者都是不同的数据库,但是具有相同的数据库tblSetting。我把它放在2个不同的程序集上(总是放在不同的程序集上),它不起作用:(
山姆

我在相同的解决方案中使用了两个程序集,并且没有出现错误,所以我不知道该评论是怎么回事...
Niklas

8

对于EF 6.x,我在https://github.com/aspnet/EntityFramework/issues/941上找到了一些注释,并在解决方案中通过向EDM类型添加注释来解决此问题。

我手动编辑了EDMX文件,并更改了如下代码:

<EntityType Name="CartItem">

对此:

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

在其他地方已有类型的情况下使用此方法:

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

其中EntityModel是用于我的EF模型的名称空间,而MyApp是业务对象的名称空间


1
这并没有为我(试过EF 6.0和6.3)工作,SQLite数据库的工作
丹尼尔TULP

:-(我只将它与MSSQL一起使用
Ekus

1
Github帖子还说要添加customannotation:UseClrTypes<EntityContainer>。(在EF 6中仍然没有为我工作)
Keith,

1
它对MSSQL和EF 6.3.0确实适用(尚未测试其他组合)。
彼得·伊凡

6

在某些情况下,这比实际问题更具症状。对我来说,当我尝试在Linq查询中调用一个函数而不先调用.ToList()时,它通常会弹出。

例如,导致我出现此错误的原因是因为我这样做:

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

我必须调用.ToList(),然后遍历每个项目并为其分配类型。


2
谢谢!这正是我的问题,在linq语句中转换为一个枚举。
道格

1

提出问题时,这可能不可用,但是另一种解决方案是删除EDMX,并将其重新创建为代码优先实体数据模型。在EF6中,使用代码优先功能,您可以从不同的模型名称空间映射两个具有相同名称的类,而不会产生冲突。

要在Visual Studio(2013)中创建实体数据模型,请转到“添加”>“新建项...”>“ ADO.NET实体数据模型”。确保选择“来自数据库的代码优先”选项。


这并没有为我(试过EF 6.0和6.3)工作,SQLite数据库的工作
丹尼尔TULP

我不知道这是否有区别,但是当我这样做时我在MS SQL Server上。
Tawab Wakil '11

这绝对对我有用。我遇到的其他解决方案似乎都不适用的情况。
戴夫

这是因为对于“代码优先”,实体类型的注释不同。请参阅@Ekus的答案stackoverflow.com/a/44931349/1307074
Suncat2000

1

我收到上面的错误,因为对于两个连接字符串,我在主项目的配置文件中指定的元数据具有相同的值,如下所示:

<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" />

我最终从EntitiesB的项目的配置文件中复制了正确的连接字符串。


我认为OP的名称实体名称存在问题。我也做过...我确实在Web.config中放入了正确的连接字符串。它仍然不起作用:(
山姆

在看到您的答案并花了3个小时弄清楚之后,解决了该问题。
ChupChapCharli

0

可能会出现此错误的另一个原因:如果要使用Assembly.LoadFile加载具有edmx文件的自定义程序集,这些自定义程序集已被加载到内存中。这将创建实体框架不喜欢的重复类。


0

对我来说,这是因为我试图在错误的上下文实例上访问具有相同名称的类型。

都说ContextAContextB拥有SomeType。我正在尝试访问ContextA.SomeType的实例ContextB


0

只需将EntityFramework添加为“来自数据库的代码优先”,而不添加为“来自数据库的EF设计器”。这解决了我的问题,但是它有一个阴暗面,如果您更改数据库,则必须删除所有类并再次添加它,或者只是编辑类,当更改列的属性时,我会使用最后一个,例如“允许null”或字符串的大小。但是,如果您添加列,建议删除并再次添加类。


0

我能够解决此问题而无需重命名类,属性或元数据。

我进行了项目设置,其中有一个T4转换在DAL项目中创建实体对象,一个T4转换在Domain项目中创建域对象,都引用EDMX生成相同的对象,然后将DAL对象映射到Domain对象。

仅当我在查询中从Domain程序集引用其他类(本例中的枚举)时,才发生该错误。当我删除它们时,错误消失了。因此,EF似乎正在加载我的Domain程序集,看到其他同名的类,然后崩溃。

为了解决这个问题,我制作了一个单独的程序集,其中仅包含T4转换的Domain类。由于我不再需要在查询中使用这些内容(仅在要映射到的查询之后),因此不再有此问题。这似乎比下面的答案更干净,更容易。


0

如果您在Web配置中有2个连接字符串,但是要使用一个连接字符串,则可以使用动态创建连接字符串的其他实体。我的解决方案中有edmx(db首先)和代码优先实体。我在Code first实体中使用此类。

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

当我称实体

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

    return _context;

}
set { _context = value; }
}

0

我认为您在实体模型中有一个名为“ MyClass”的类X,并且在第一个类的同一WorkFolder或Extended中具有另一个称为“ MyClass”的类。那是我的问题,我解决了。


-9

您可以下载一个名为AutoMapper的库。它可以帮助您定义从一种类型到另一种类型的类映射。

Mapper.CreateMap<Model.FileHistoryEFModel, DataTypes.FileHistory>();
Mapper.CreateMap<DataTypes.FileHistory, Model.FileHistoryEFModel>();

12
并不是真正适用于用户的问题。使用自动映射器并不能解决他的问题。
加尔文
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.