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数据( SSDL
和MSL
部分)。 消防,现在有两个例外:
-
检索
Meals
会引发MSL, error 2062 No mapping specified for instance of the EntitySet and AssociationSet in the EntityContainer
。 -
检索
Drinks
继续抛出The entity type Drinkis not part of the model for the current context
。
由Meals
引发的错误是预期的,我修改了映射和存储模型 – 检查_db
向我显示Meals
– > InternalSet
– > EntitySet
属性是正确的,只是没有映射。
Drinks
抛出的错误是我被困住的地方。 检查_db
告诉我Drinks
– > InternalSet
– > EntitySet
会抛出SystemInvalidOperation
exception,该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之前,我遇到了同样的问题
使用它,您可以生成明确的实体,如业务对象和映射类。 帮助我创建出色的数据访问层的好文章: 逆向工程师代码优先