使用实体框架将行插入到具有复合键的表中
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 设置为主键,因为它永远无法确定它是唯一的。以上是关于使用实体框架将行插入到具有复合键的表中的主要内容,如果未能解决你的问题,请参考以下文章
使用 CodeIgniter 框架将数据插入到具有外键的多个表中