我正在尝试从实体框架中更新复合主键的一个值,并且我收到此错误:“属性'CustomerID'是对象的关键信息的一部分,无法修改。”
这是我的代码:
Dim customer As Customer = (From c In db.Customer Where c.CustomerID = "xxx" AndAlso c.SiteKey = siteKey).FirstOrDefault
customer.CustomerID = "fasdfasdf"
db.SaveChanges()
看起来太简单了。是否真的无法在实体框架内更新主键?我找不到有关该主题的任何文档。谢谢!
答案 0 :(得分:55)
答案 1 :(得分:21)
您无法通过实体框架更新主键,因为实体框架不知道要更新哪个数据库行。
但是,如果确实需要这样做,可以编写一个更新主键的存储过程,然后从实体框架中执行存储过程。
答案 2 :(得分:10)
你不能并且有充分的理由。见KM评论。
我说你可以做的一件事是有两个表,一个是匿名数据,一个是在登录后存储真实用户数据。
或者你的(我没有经过测试或曾经做过)可以使用这种表布局:
---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.
当他们登录时,您将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表关系中的任何表仍然有效,并且不必对主键进行级联更新(这就像用铅笔刺伤自己的眼睛一样)。
答案 3 :(得分:0)
如果在任何时候都可能只有一个数据库上下文实例,那么修改pk不会是一个问题。但是每个上下文实例都维护自己的缓存,并且可以缓存要修改的记录。
EF与数据库的交互使用pk(来自上下文缓存)来标识它们正在查询的记录。如果上下文对象可以更新持久性密钥,则其他上下文对象用来标识该记录的信息将立即且永久错误。
简而言之,如果您更新主键,则可能会使上下文的所有其他实例中的缓存无效,这将从根本上破坏EF。这是更新pk不好的主要原因之一。
答案 4 :(得分:-3)
您无法更新主键,但这不是实体框架的限制,而是数据库开发的一个非常基本的规则。主键一次分配给表中的一行,并使该行唯一 也许你可以在某些方面更新密钥,但这肯定违反了主键的定义。
所以,只是不要这样做,还有其他方法可以完成你想要做的事情。