使用实体框架将行插入到具有复合键的表中

Posted

技术标签:

【中文标题】使用实体框架将行插入到具有复合键的表中【英文标题】:Using Entity Framework to insert row to a table that has a composite key 【发布时间】:2012-02-07 09:06:18 【问题描述】:

我正在使用 Entity Framework 向数据库表中插入一个新行,但我的问题是 ValidFromDate 列导致异常

“ValidFromDate”属性是对象关键信息的一部分 并且不能修改日期

我们的 DBA 已经定义了数据库,下图是 EDMX 文件的快照。 ValidFromDate日期时间 列。

FarmAnimal 的想法是跟踪某些动物的历史。因此AnimalId ValidFromDate 导致该行是唯一的。

现在的问题是,我怎样才能在具有这种模式的表中插入新行?

使用实体框架插入

var farmAnimal = new FarmAnimal 
   AnimalId = insert.AnimalId,
   ValidFromDate = insert.ValidFromDate // exception comes from this line,
   etc.
;
entities.FarmAnimals.Add(farmAnimal);

更新:StackTrace

   at System.Data.Objects.EntityEntry.DetectChangesInProperties(Boolean detectOnlyComplexProperties)
   at System.Data.Objects.ObjectStateManager.DetectChangesInScalarAndComplexProperties(IList`1 entries)
   at System.Data.Objects.ObjectStateManager.DetectChanges()
   at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
   at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
   at System.Data.Entity.DbSet`1.Add(TEntity entity)
   at xxx.Repositories.PairingRepository.UpdateFarmAnimals(IEnumerable`1 updates, IEnumerable`1 inserts) in xxx
   at xxx.Services.PairingService.RemovePairingAnimals(List`1 animalIds) in xxx
   at xxx.Controllers.PairingController.RemovePairingAnimals(List`1 animalIds) in xxx
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)

更新 2:实体框架文件

我添加了三个文件实体框架映射文件/生成器 EDMX 文件 ADO.NET DbContext 生成器 ADO.NET EntityObject 生成器(POCO)

【问题讨论】:

什么时候出现异常?保存更改时的设置器之一,ObjectSet.Add 方法?你能发布堆栈跟踪吗? @cynic 查看源代码块的注释。我现在将获取堆栈跟踪。感谢您的宝贵时间。 我看到您正在使用 DbSet/DbContext 包装层。实体是 POCO,还是使用所有更改跟踪逻辑生成的? 另外,当内存上下文 (FarmAnimals.Local) 中至少存在一个 FarmAnimal 时,我认为调用失败? @cynic 我假设我的 .tt 文件不是“ADO.NET 自跟踪实体生成器”,因为生成的 .cs 文件似乎只包含 POCO。 【参考方案1】:

DbSet 包装器在对新的 FarmAnimal 执行任何操作之前就失败了 - 在底层 ObjectContext 上的 AddObject 之前调用了 DetectChanges,它以某种方式检测到已加载/添加到上下文中的 FarmAnimal 中的禁止更改。如果您使用带有代理的 POCO,或者只是使用更改跟踪生成的普通无聊类(这与“自我跟踪实体”不同,只是使用 vanilla VS2010 添加新数据模型时生成的类),您可以turn off automatic detection of changes 这样它就不会被调用。

【讨论】:

我对您的解决方案进行了第一次测试。它似乎有效,我将再测试一点,然后将其标记为答案。谢谢! 在提供的链接(章节“禁用自动检测更改”)中进行类似设置后可以顺利运行。 20小时后,我可以奖励赏金。感谢您的帮助。【参考方案2】:

我很惊讶它没有提前崩溃,因为 AnimalId 和 ValidFromDate 都是 PrimaryKeys,AnimalId imo 永远不应该在你的代码中设置,而应该是一个自动计数器。

在搜索“该属性是对象的关键信息的一部分,不能修改日期”后,我得到了这个命中:http://forums.asp.net/t/1747622.aspx/1

这可能会比我解释得更好

【讨论】:

记住这不是Animal表,所以AnimalId本身并不是唯一的,而是AnimalId和ValidFromDate的组合。在 Animal 表中有 AnimalId 的自动计数器。 我还是不明白为什么它们都是PrimaryKeys。我的猜测是 EF 不允许您将 DateTime 设置为主键,因为它永远无法确定它是唯一的。

以上是关于使用实体框架将行插入到具有复合键的表中的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 对具有复合键的子实体执行错误的插入顺序

使用复合键的许多人:如何在实体之间的表中添加元素?

具有存储库模式的实体框架,将数据插入到具有多对多关系的表中

使用 CodeIgniter 框架将数据插入到具有外键的多个表中

如何进行 Hibernate XML 映射,一对多使用 1 PK 映射到另一个具有复合键的实体

实体框架代码优先:具有两个外键的表