0

私はUserエンティティクラスを持っている:エンティティフレームワーク - ビュー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; 
    } 
} 

私は私のウェブ設定ポータル(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); 
    } 

は、私だけUserWCPModelを渡すことによって、リポジトリからUpdateメソッドを呼び出します。私は空白のUserオブジェクトを構築

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ユーザーに添付します。
  4. UserWCPModelからUserオブジェクトにデータを読み込みます。
  5. 変更した時刻を設定しました(重要ではありません)。
  6. 私はdb.SaveChanges()を呼び出します(これはSaveToDbの動作です)。

ゴール達成! 2番目のSELECTクエリがありません。 モデルに関連しない保存データはありません。 すべてのプロパティに対してIsModifiedの呼び出しがありません。 以前に入力したモデルの範囲外のデータに対する害はありません。

私はひどく、私はここでそれを共有する必要があること、それを微調整、およびいくつかのコメントへの希望:D

ホープ誰かが見つけるこの便利な:)

+0

データベース内に* optional/nullable *の列がありますが、UIの*必須の*プロパティがあるため、DBとUIを意図的に「不一致」にしているためです。多分あなたはそれを望んでいるか必要としているかもしれませんが、私はこれを非常に特殊なアーキテクチャと呼んでいます。 – Slauma

答えて

1

あなたはエンティティあなたを更新するため、この方法を使用している場合本当に注意する必要があります。同じコンテキストで同じエンティティを2回試して更新しようとするとどうなるでしょうか?あなたがアップされるまで、読み取り専用のエンティティに作用するように、また

は、私はあなたがすべてのクエリに.AsNoTracking()を(my blog post on AsNoTrackingを参照)を追加推薦する:(スポイラーは、すでに装着されているエンティティを添付しようとすると、例外が発生します)実際に更新を実行します。これは、エンティティをコンテキストに二重に付加するのを避けるのにも役立ちます。

パフォーマンス上の理由から絶対にこの方法を使用する必要がない限り、この方法は危険な地面を歩いているように思えます。私の意見では、まずdbからエンティティを取得し、プロパティを手動で更新して保存するほうがはるかに良いでしょう。これはおそらくあなたの頭痛を長期的に保存します。

関連する問題