我有一个User实体类:
public class User
{
[Key]
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string SecretQuestion { get; set; }
public string SecretAnswer { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public Nullable<byte> UserType { get; set; }
public Nullable<bool> Enabled { get; set; }
public Nullable<DateTime> Created { get; set; }
public Nullable<DateTime> Modified { get; set; }
public void LoadWCPModel(UserWCPModel model)
{
Username = model.Username;
Password = model.Password;
SecretQuestion = model.SecretQuestion;
SecretAnswer = model.SecretAnswer;
UserType = model.UserType;
Enabled = model.Enabled;
}
}
我的Web配置门户(WCP)有一个模型类:
public class UserWCPModel
{
[Key]
public int UserId { get; set; }
[Display(Name = "Username")]
[Required]
public string Username { get; set; }
[Display(Name = "Password")]
[Required]
public string Password { get; set; }
[Display(Name = "Secret question")]
[Required]
public string SecretQuestion { get; set; }
[Display(Name = "Secret answer")]
[Required]
public string SecretAnswer { get; set; }
[Display(Name = "User type")]
[Required]
public Nullable<byte> UserType { get; set; }
[Display(Name = "Enabled")]
[Required]
public Nullable<bool> Enabled { get; set; }
[ScaffoldColumn(false)]
public Nullable<DateTime> Created { get; set; }
[ScaffoldColumn(false)]
public Nullable<DateTime> Modified { get; set; }
/// Parameterless constructor for MVC model binder.
public UserWCPModel()
{
Created = DateTime.UtcNow;
}
}
目标:获取UserWCPModel并仅保存该模型中的数据,而不会损害其他应用程序(电子邮件,电话,全名)填充的数据,同时还完全避免从数据库重新加载数据。
首先,HttpPost Edit操作:
[HttpPost]
public ActionResult Edit(UserWCPModel model)
{
if (ModelState.IsValid)
{
WrappedE result;
repo.Update(model, out result);
if (result.ErrorCode != ErrorCodes.Success)
{
/// Add error handling;
}
return RedirectToAction("Index");
}
return View(model);
}
如您所见,我只通过传递UserWCPModel从存储库调用Update方法。
现在这里是存储库方法:
public void Update(UserWCPModel model, out WrappedE result)
{
User user = new User();
user.UserId = model.UserId;
db.Users.Attach(user);
user.LoadWCPModel(model);
user.Modified = DateTime.UtcNow;
SaveToDb(out result);
}
目标完成了! 没有第二个SELECT查询。 没有与模型无关的保存数据。 没有为每个属性调用IsModified。 对先前输入的超出模型范围的数据没有任何损害。
我调整得非常糟糕,我必须在这里分享它,并希望得到一些评论:D
希望有人会觉得这很有用:)
答案 0 :(得分:1)
如果您使用此方法更新实体,则需要非常小心;如果您尝试在同一上下文中两次更新同一实体,将会发生什么。 (剧透:当你试图附加一个已经附加的实体时,你会得到一个例外)
此外,我建议您向所有查询添加.AsNoTracking()
(请参阅my blog post on AsNoTracking),以便在实际执行更新之前对只读实体执行操作。这也有助于避免将实体双重附加到您的上下文中。
我认为这种方法对我而言似乎是在踩着危险的地方,除非你出于性能原因绝对需要使用这种方法。在我看来,首先从db获取实体并手动更新属性并保存它会更好。从长远来看,这可能会让您头疼不已。