使用实体框架更新主键值

时间:2009-09-02 13:41:36

标签: .net sql-server vb.net 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()

看起来太简单了。是否真的无法在实体框架内更新主键?我找不到有关该主题的任何文档。谢谢!

5 个答案:

答案 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)

您无法更新主键,但这不是实体框架的限制,而是数据库开发的一个非常基本的规则。主键一次分配给表中的一行,并使该行唯一 也许你可以在某些方面更新密钥,但这肯定违反了主键的定义。

所以,只是不要这样做,还有其他方法可以完成你想要做的事情。