0

我有一個用戶實體類:實體框架 - 查看2斷開實體更新

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編輯動作:

[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); 
    } 

正如你所看到的,我只能從庫調用Update方法,通過傳遞UserWCPModel。

現在,這裏是倉庫方法:

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); 
    } 
  1. 我構建空白的用戶對象。
  2. 我從模型中分配它的ID。
  3. 我將它附加到DbSet Users。
  4. 我從UserWCPModel加載數據到用戶對象。
  5. 我設置修改時間(不重要)。
  6. 我調用db.SaveChanges()(這是SaveToDb的作用)。

目標完成! 沒有第二個SELECT查詢。 不保存與模型無關的數據。 沒有爲每個屬性調用IsModified。 以前輸入的數據超出了模型範圍。

我調整它如此糟糕,我要在這裏分享,併爲一些意見希望:d

希望有人會覺得這有用:)

+0

它的工作原理,但只是因爲你有意使DB和UI「不一致」,可以這麼說,因爲你在數據庫中有* optional/nullable *列,但是*在UI中需要*屬性。也許你想或需要,但我會稱這是一個非常「特殊」的架構。 – Slauma

回答

1

如果您正在使用更新您的實體此方法需要非常小心; conciser如果你嘗試在相同的上下文中更新同一個實體兩次,會發生什麼。 (破壞者:當你嘗試附加一個已經連接的實體時,你會得到一個例外)

另外,我會建議你爲所有查詢添加.AsNoTracking()(見my blog post on AsNoTracking),以便直到你實際上執行更新。這也有助於避免將實體附加到您的上下文中。

我想這種方法對我來說似乎就像是踩在危險的地面上,除非你絕對需要使用這種方法來提高性能。在我看來,你會更好地從數據庫中獲取實體,並手動更新屬性並保存它。這可能會爲你長期解決頭痛問題。