使用entity framework更新主键值
我试图从entity framework内更新复合主键的一个值,我得到这个错误:“属性”CustomerID“是对象的关键信息的一部分,不能被修改。
这是我的代码:
Dim customer As Customer = (From c In db.Customer Where c.CustomerID = "xxx" AndAlso c.SiteKey = siteKey).FirstOrDefault customer.CustomerID = "fasdfasdf" db.SaveChanges()
这似乎太简单了。 这是真的,你不能更新entity framework内的主键? 我找不到有关该主题的任何文档。 谢谢!
你不能,并有充分的理由。 请参阅KM评论。
我说你可以做的一件事就是拥有两个匿名数据表,一个存储login后的真实用户数据。
或者你可以(没有testing或者做过我)有这样的表格布局:
---Customers---- AutoNumber PK <- This links to all other tables in your database, and does NOT change. CustomerID <- This can change. CustomerType <- Anonymous or logged in.
而当他们login时,您将CustomerType和CustomerID更改为您所需的。
所以你的查询可能看起来像这样:
Dim customer As Customer = (From c In db.Customer _ Where c.CustomerID = {Some temp ID} _ AndAlso c. CustomerType = "Anonymous").FirstOrDefault // After user logs in. customer.CustomerID = {Make a new user ID here} customer.CustomerType = "LoggedIn" {or what ever} db.SaveChanges()
请注意,自动编号主键从不改变。 这样,您与Customers表关联的任何表仍然可以工作,而不必在主键上进行级联更新(就像用铅笔在眼睛中刺入自己)。
我有一个博士学位。 在cs中 – 在数据库领域,所以这个答案会有点不同于程序员的观点。 对于奥利弗·哈奈皮(Oliver Hanappi)来说,如果不是代理关键,那么关键是偶尔也会改变。 例如,一个自然键或一个合成键。 例如。 美国有可能改变你的SSN。 但是这些年来很多程序员会认为这是一个不可改变的关键,并将其用于此。 更改由外键组成的复合主键更为常见。
我正在处理一个具有三元关系的数据库。 特别是三个实体(外键在它们各自的表中代理主键)。 但是,在更改第三个实体时要保留两个实体之间的关系, 需要更改部分交集表(也称为MSDN上的纯联接表)主键。 这是一个有效的devise,只能通过删除三元关系交点表并用两个二元关系表(可能有自己的代理键)来替代。 EF会处理这个罚款。 这种devise变更会使一个(Many-> many) – > many或Parent1-Parent2 – > Child-grandchild模型(如果不清楚,请阅读下面的例子)。 entity framework可以正常工作,因为每个关系实际上是一对多的关系。 但从数据库的angular度来看这是一个疯狂的devise。 让我告诉你一个例子,为什么。
考虑课程,课堂和讲师在课堂上是相互关联的。 Class可以包括:CourseID,ClassroomID,InstructorID作为外键,并包含一个包含所有三个键的组合主键。 虽然一个清晰,简明的三元模型(3路关系),我们可以把它分解成二元关系。 这会给两个相交表。 添加代理键将满足EF如下:
类( SurrogateKeyClass , InstructorID , CourseID )
ClassRoomUsed( SurrogateKeyClassroomUsed , SurrogateKeyClass , ClassRoomID )
这个devise的问题是我们可以有相同的课程和教师多次关联,这是以前的模型所避免的。 为了避免这个问题,你可以在数据库中添加一个约束来保证两个ID字段的唯一性,但是为什么当你只处理代理键时呢? 但是,这个解决scheme将尽我所能地工作。 然而,这不是逻辑数据库devise,因为DB中需要不自然的唯一约束。
但是,如果你不想改变你的数据库或不能改变你的数据库,这里是第二个解决scheme :交集/关联表就是这样,链接两个实体或更多的链接在一起。 如果更改,删除关联并重新创build一个具有适当的外键(导航属性)。 这意味着你不会被允许在任何关系中要求儿童实体,但这是非常普遍的。
我会build议entity framework(在将来)允许我们这些谁可以devise一个优雅的数据库模型来改变我们想要的交集/关联表中的部分键!
免费的另一个例子:
考虑一个学生,课程,年级协会。 学生通过一个等级与课程相关联。 通常这是学生和课程之间的多对多关联,在关联表中有一个额外的字段,称为成绩(关联表具有有效载荷数据,例如成绩,交叉表没有有效载荷,并且在MSDN中被称为纯连接表租赁在一个地方):
学生( StudentID ,….)
课程( CourseID ,…)
以( StudentID , CourseID ,等级)
如果有人从下拉菜单中input数据,并将学生放在错误的class级中,您可以稍后再次select下拉菜单并select其他课程,以便他们进行更改。 在后台,您需要从收集表中删除EF对象,并重新创build它,而不会丢失成绩(如果有的话)。 只需更改外键CourseID似乎是一个更好的select。 如果这件事看起来有些勉强,那就拿出自己的协会吧,但作为教授,这对我来说是很自然的。
结论:当你有一串关系时,最好不要让级联和/或改变FK,但是在需要的地方存在合理/合理的场景,即使不被推荐为一般的最佳实践。
此问题可能会出现以下exception,具体取决于是否分别更改模型中的导航属性或键属性:
发生了参照完整性约束冲突:除非将关联对象设置为关联的主体对象,否则当从属对象为Unchanged时,作为参照完整性约束的一部分的主键属性无法更改。 主要的对象必须被跟踪,并且没有被标记为删除。
属性“X”是对象的关键信息的一部分,不能被修改。
你不能通过entity framework更新主键,因为entity framework不知道要更新哪个数据库行。
但是,如果您确实需要这样做,则可以编写一个更新主键的存储过程,然后从entity framework中执行存储过程。
你不能更新主键,但这不是entity framework的限制,而是数据库开发的一个非常基本的规则。 主键被分配一次到表中的一行,并使该行是唯一的。
也许你可以在某些方面更新密钥,但是这肯定违反了主键的定义。
所以,不要这样做,还有其他方法可以完成你正在做的事情。