协慌网

登录 贡献 社区

实体框架 5 更新记录

我一直在探索在 ASP.NET MVC3 环境中编辑 / 更新实体框架 5 中的记录的不同方法,但到目前为止,它们都没有勾选我需要的所有框。我会解释原因。

我找到了三种方法,我将提到它的优点和缺点:

方法 1 - 加载原始记录,更新每个属性

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    original.BusinessEntityId = updatedUser.BusinessEntityId;
    original.Email = updatedUser.Email;
    original.EmployeeId = updatedUser.EmployeeId;
    original.Forename = updatedUser.Forename;
    original.Surname = updatedUser.Surname;
    original.Telephone = updatedUser.Telephone;
    original.Title = updatedUser.Title;
    original.Fax = updatedUser.Fax;
    original.ASPNetUserId = updatedUser.ASPNetUserId;
    db.SaveChanges();
}

优点

  • 可以指定更改哪些属性
  • 视图不需要包含每个属性

缺点

  • 在数据库上进行 2 次查询以加载原始数据然后更新它

方法 2 - 加载原始记录,设置更改的值

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    db.Entry(original).CurrentValues.SetValues(updatedUser);
    db.SaveChanges();
}

优点

  • 仅将已修改的属性发送到数据库

缺点

  • 视图需要包含每个属性
  • 在数据库上进行 2 次查询以加载原始数据然后更新它

方法 3 - 附加更新的记录并将状态设置为 EntityState.Modified

db.Users.Attach(updatedUser);
db.Entry(updatedUser).State = EntityState.Modified;
db.SaveChanges();

优点

  • 1 x 查询数据库以进行更新

缺点

  • 无法指定更改哪些属性
  • 视图必须包含每个属性

我向你们提问; 有没有一种干净的方式可以达到这套目标?

  • 可以指定更改哪些属性
  • 视图不需要包含每个属性(例如密码!)
  • 1 x 查询数据库以进行更新

我明白这是一个很小的事情要指出,但我可能错过了一个简单的解决方案。如果不是方法一将占上风;-)

答案

您正在寻找:

db.Users.Attach(updatedUser);
var entry = db.Entry(updatedUser);
entry.Property(e => e.Email).IsModified = true;
// other changed properties
db.SaveChanges();

我真的很喜欢接受的答案。我相信还有另一种方法可以解决这个问题。假设您有一个非常短的属性列表,您不希望在 View 中包含这些属性,因此在更新实体时,这些属性将被省略。假设这两个字段是密码和 SSN。

db.Users.Attach(updatedUser);

var entry = db.Entry(updatedUser);
entry.State = EntityState.Modified;

entry.Property(e => e.Password).IsModified = false;
entry.Property(e => e.SSN).IsModified = false;   

db.SaveChanges();

此示例允许您在向 Users 表和 View 添加新字段后,基本上保留业务逻辑。

foreach(PropertyInfo propertyInfo in original.GetType().GetProperties()) {
    if (propertyInfo.GetValue(updatedUser, null) == null)
        propertyInfo.SetValue(updatedUser, propertyInfo.GetValue(original, null), null);
}
db.Entry(original).CurrentValues.SetValues(updatedUser);
db.SaveChanges();