1

EF5 和架构中的非空字符串出现了一些谜团。例如,假设我们有这个简单的用户表:

CREATE TABLE Users
(
   UserID INT PRIMARY KEY NOT NULL IDENTITY(1,1),
   UserName VARCHAR(50) NOT NULL,
   UserFirst VARCHAR(50) NULL,
   UserLast VARCHAR(50) NULL
)

...我创建了一个 POCO 类来表示它。这一切都很好。我可以检索和创建数据,但是更新造成了一些严重的痛苦。假设我想更新给定用户的名字:

User user = new User { UserID = 12345 };
context.Users.Attach(user);
user.FirstName = "SomethingElse";
context.SaveChanges();

这应该有效。附加后,不可为空UserName的为空。哪个应该没问题 - 我不想更改它,并且更改检测表明该值未更改。但是,当我调用 时SaveChanges,会抛出一个 DB 验证异常,说明它UserName是无效的。

所以,从这里,有两个问题:

  1. 我做错了什么?我完全愿意相信我对实体框架的理解是有缺陷的。
  2. 为什么在保存时不使用按属性更改状态?我知道context.Configuration.ValidateOnSaveEnabled,但我不认为简单地关闭验证是一个有效的答案。我可以依靠另一个类似的选择吗?
4

1 回答 1

2

您说您要更新用户,但您的示例代码正在创建一个新用户,其 ID 为 12345,然后附加它。您的代码正在做的是创建一个全新的实体,将不可为空的字段留空,并尝试保存到数据库,这会引发错误。

您是否打算检索 ID 为 12345 的现有用户?然后,您应该从数据库中获取该实体,然后更新属性,而不是创建新实体。

User user = context.Users.First(u => u.UserID == 12345);
user.FirstName = "SomethingElse";
context.SaveChanges();

编辑

发生的情况是,当您在附加后修改 FirstName 属性时,EF 将整个实体标记为脏,因此它会尝试更新所有内容。

如果您只想更新 FirstName,您需要更改您的代码(来自相关的 SO 帖子,如何更新单个列):

  var user = new User { UserID = 12345, FirstName = "SomethingElse" };
  using (var db = new MyEfContextName())
  {
    context.Users.Attach(user);
    context.Entry(user).Property(x => x.FirstName).IsModified = true;
    context.SaveChanges();
  }
于 2012-09-25T13:22:07.377 回答