Entity framework EF5附加实体验证

Entity framework EF5附加实体验证,entity-framework,Entity Framework,模式中的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类来表示它。这一切都很好。我可以检索和创建数据,但是更新造成了一些

模式中的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();
这应该行得通。附件后,不可为空的
用户名
为空。这应该很好-我没有试图更改它,更改检测表明该值未更改。但是,当我调用
SaveChanges
时,会抛出一个DB验证异常,说明
用户名
无效

因此,从这一点来看,有两个问题:

  • 我是不是做错了什么?我完全愿意相信我对实体框架的理解是有缺陷的
  • 为什么在节省时间时不使用“按属性更改状态”?我知道
    context.Configuration.ValidateOnSaveEnabled
    ,但我不认为简单地关闭验证是一个有效的答案。还有其他类似的选择吗

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

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

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

    当您在附加之后修改FirstName属性时,EF会将整个实体标记为dirty,因此它会尝试更新所有内容

    如果只想更新名字,则需要更改代码(从a):


    我明白你的意思,但我不同意。从
    Attach
    :“…实体被置于未更改状态,就像它是从数据库中读取的一样。”换句话说,
    UserName
    为null这一事实应该是无关紧要的,因此,验证应该是按属性,而不是按对象。(此外,如果您设置了相同的场景,但在EDMX中将默认值设置为空字符串,则无需在保存时设置
    用户名
    ,并且空字符串不会持久化。)我还不清楚的是,当实体显式公开
    IsModified
    时,为什么该实体被标记为脏批发。在我看来,应该只检查
    已修改的
    字段,在我原来的情况下,只修改了一个字段。然而,仔细考虑之后,试图使上下文足够智能以零碎地保存实体——特别是从代码优先的角度来看——将是相当令人畏惧的。使用聪明的模板是可行的,但我不确定是否值得为此项目付出努力。
    
      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();
      }