EntitySet System.InvalidOperationException – “实体类型不是当前上下文模型的一部分”

类似的问题

实体类型不是当前上下文的模型的一部分 – 并且 – EF 4.1 Code First错误 – 实体类型SomeType不是当前上下文的模型的一部分是类似的问题,但它们是“代码优先”透视图只有更简单的数据模型,并解决连接字符串和映射问题。 请仔细看看这个。

症状

// HomeController.cs public ActionResult Index() { var _db = new MealsContext(); var m = _db.Meals.ToList(); var d = _db.Drinks.ToList(); return View(); } 

检索Drinks集合时会抛出exception:

 The entity type Drink is not part of the model for the current context. 

 // Meal.cs public class Meal { public int Id { get; set; } public string Stuff { get; set; } public virtual ICollection Meats { get; set; } public virtual ICollection Vegetables { get; set; } } // Meat.cs public class Meat { public int Id { get; set; } public string Name { get; set; } public int MealId { get; set; } } // Vegetable.cs public class Vegetable { public int Id { get; set; } public string Name { get; set; } public int MealId { get; set; } } // Drink.cs public class Drink { public int Id { get; set; } public string Name { get; set; } } 

是的,我知道在现实世界中,肉类和蔬菜与膳食之间的关系很可能是多对多,但不要挂在这里。

 // MealsContext.cs public class MealsContext: DbContext { public MealsContext() : base("ConnectionString") public DbSet Meals{ get; set; } public DbSet Meats{ get; set; } public DbSet Vegetables { get; set; } public DbSet Drinks{ get; set; } } 

我的经验是使用Model First方法。 EDMX文件是在POCO之后构建的。

在连接字符串中是映射到已解析的EDMX资源的元数据部分( metadata=res://*/Models.MealsModels.csdl|res://*/Models.MealsModels.ssdl|res://*/Models.MealsModels.msl; )。

我检查了EDMX文件的基础XML,显示了Conceptual和Store模型中的所有实体,并且所有实体都已完全映射。 WTF?

故障排除

第一个尝试是完全摆脱存储和映射EDMX数据( SSDLMSL部分)。 消防,现在有两个例外:

  1. 检索Meals会引发MSL, error 2062 No mapping specified for instance of the EntitySet and AssociationSet in the EntityContainer

  2. 检索Drinks继续抛出The entity type Drinkis not part of the model for the current context

Meals引发的错误是预期的,我修改了映射和存储模型 – 检查_db向我显示Meals – > InternalSet – > EntitySet属性是正确的,只是没有映射。

Drinks抛出的错误是我被困住的地方。 检查_db告诉我Drinks – > InternalSet – > EntitySet会抛出SystemInvalidOperationexception,该exception表明实体不在模型上下文中。

以下是EDMX的CSDL在XML格式中的样子:

                     

如果DbContext具有所有DbSet属性并且正在使用连接字符串,该连接字符串包含CSDL正确定义实体类型Drink的模型的元数据, 为什么在地狱中它不是上下文的一部分?

我能看到的唯一与Drink不同的是它与任何其他实体无关,并且没有关联……

解决了。

上半场是我的疏忽。 下半场……好吧,我没说错。 这不是一个真正的错误或不兼容,但非常不方便,间歇性和难以弄清楚。 首先是摘要,然后是那些关心的人的长度解释:

尽管存在错误消息建议,但它不是概念模型(CSDL)的问题,而是间歇性地重新创建自身的列映射问题。

概念模型是使用EdmxWriter用于解析DbContext及其底层部分。

然后,该模型用于生成SQL脚本以将架构推送到新数据库。 诀窍是,数据库是Oracle。

甲骨文是一个婴儿,不接受长列名称。 因此,必须修改生成的EDMX和SQL脚本,以构建概念模型的部分并将其映射到截断的列名。

没什么大不了的。 它工作正常。 那么事情出了什么问题?

Oracle不支持“代码优先”。 即使它是手动完成的,使用EdmxWriter构成了Oracle眼中的代码优先方法。 因此,当第一个EDMX模式被解析时,它就是关于布尔映射的。 解决方案是暂时从我的C#模型中删除bool ,手动将它们添加到EDMX并进行Oracle建议的web.config映射(将bool映射到NUMBER(1,0) )。

一切都很时髦了。 但为什么它会重复出现?

在整个开发过程的不同时间,协议的某些目标–C#,EDMX或Oracle – 都会被更改。 每一次,似乎列都被自动重新映射,我不知道。 如果从Oracle刷新EDMX模型,则映射指向不存在的C#属性(短列名称)。 如果从C#代码刷新模型,则不会保留映射,并且它们会尝试映射到Oracle中不存在的长列名称。

如果我想继续管理我自己的模型并处理Oracle小宝贝态度所需的自定义,那么这种方法有点糟糕( 首先是混合代码和模型优先 ),我必须非常小心并监视EDMX文件的地狱。

您需要为实体指定映射:

 public class MealsContext: DbContext { public MealsContext() : base("ConnectionString") protected override void OnModelCreating(DbModelBuilder modelBuilder) { // mappings } public DbSet Meals{ get; set; } public DbSet Meats{ get; set; } public DbSet Vegetables { get; set; } public DbSet Drinks{ get; set; } } 

在我开始使用Entity Framework Power Tools之前,我遇到了同样的问题

使用它,您可以生成明确的实体,如业务对象和映射类。 帮助我创建出色的数据访问层的好文章: 逆向工程师代码优先