2013-05-22 6 views
6

を使用して、コントローラでは、モデルプロパティの状態変化を検出:は、私は、多かれ少なかれ標準探しのモデルを持っているEntity Frameworkの

public class Project { 
    public int ID { get; set; } 
    //... some more properties 

    public DateTime StartDate { get; set; } 
    public int Duration { get; set; } 
} 

ユーザーがStartDateまたはプロジェクトDurationを変更した場合、私は更新する機能を呼び出す必要がありますシミュレーション。これを達成するために、コントローラー内のフィールドStartDateDurationの状態変化を検出したいと思います。そのような

何か:ここ

if(project.StartDate.stateChange() || project.Duration.stateChange()) 

は、コントローラのメソッドがどのように見えるかの例です:

[HttpPost] 
public ActionResult Edit(Project project) 
{ 
    if (ModelState.IsValid) 
    { 
     if(project.StartDate.stateChange() || project.Duration.stateChange()) 
      doSomething(); 

     db.Entry(project).State = EntityState.Modified; 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(project); 
} 

任意のアイデアを、どのように私はこれを達成することができますか?

答えて

7

私はあなたがデータベースから読み取られた元のものと編集された実体を比較することができると信じています。あなたはViewBag経由で古い値を運ぶことによってそれを解決することができ

public ActionResult Edit(Project project) 
{ 
    if (ModelState.IsValid) 
    { 
     var original = db.Find(project.ID); 
     bool changed = original.StartDate != project.StartDate || original.Duration != project.Duration; 
     if (changed) 
     { 
      original.StartDate = project.StartDate; 
      original.Duration = project.Duration; 
      doSomething(); 
      db.Entry(original).State = EntityState.Modified; //not sure if this is necessary as it should be tracked by EF (because it is read from the database) 
      db.SaveChanges(); 
     } 
    } 
    return View(project); 
} 
+1

私はこれを試しました。次のエラーが表示されます。 'ObjectStateManagerに同じキーを持つオブジェクトが既に存在します。 ObjectStateManagerは、同じキーを持つ複数のオブジェクトを追跡できません。 説明:現在のWeb要求の実行中に、未処理の例外が発生しました。エラーの詳細とコード内のどこで発生したのかについては、スタックトレースを参照してください。 例外の詳細:System.InvalidOperationException:ObjectStateManagerに同じキーを持つオブジェクトが既に存在します。 ObjectStateManagerは同じキーを持つ複数のオブジェクトを追跡できません。 ' – Chopo87

+0

' db.Entry(元).State = EntityState.Modified;の有無にかかわらず? –

+0

良い点は、それを試してみましょう – Chopo87

2

あなたのパーシスタンスレイヤーを照会せずにそれをしたいのであれば、古い値をモデルのフィールドとして追加して、隠れフィールドとしてページに保持するのがこれを解決する最も簡単な方法です。これはあなたの選択を比較するために何かを与える

@Html.HiddenFor(model => model.CurrentStartDate) 
@Html.HiddenFor(model => model.CurrentDuration) 

public class Project { 
    public int ID { get; set; } 
    //... some more properties 

    public DateTime StartDate { get; set; } 
    public int Duration { get; set; } 

    public DateTime CurrentStartDate { get; set; } 
    public int CurrentDuration { get; set; } 
} 

をして、あなたのビューで古い値を持つ隠しフィールドを追加します。

だからあなたのモデルにCurrentStartDateとCurrentDurationを追加あなたのコントローラーのアクションに値があります。

+1

実際には、可能であればコントローラー内のすべてのチェックを行い、コードをきれいに保ちます。あなたの「永続化レイヤーを照会する」方法を拡張することができますか、それは私が達成しようとしているもののように思えます。 – Chopo87

+1

次に、dbから現在のプロジェクトを取得し、古い値をチェックして、クライアントから取得している値と比較する必要があります。 – KMan

+1

私はすでにそれを試みました:次の例外があります。 'ObjectStateManagerに同じキーを持つオブジェクトが既に存在します。 ObjectStateManagerは同じキーを持つ複数のオブジェクトを追跡できません。 ' – Chopo87

6

:よう

何か。アクションで

public ActionResult Edit(int? id) 
{ 
    //...Your Code 
    ViewBag.OrigStartDate = project.StartDate; 
    ViewBag.OrigDuration = project.Duration; 
    return View(project); 
} 

... 
@Html.Hidden("OrigStartDate", (DateTime)ViewBag.OrigStartDate) 
@Html.Hidden("OrigDuration", (int)ViewBag.OrigDuration) 
... 

POSTメソッドにこれらのパラメータを追加し、変更

[HttpPost] 
public ActionResult Edit(DateTime OrigStartDate, int OrigDuration) 
{ 
    if (ModelState.IsValid) 
    { 
     if (OrigStartDate != project.StartDate || OrigDuration != project.Duration) 
      doSomething(); 

     db.Entry(project).State = EntityState.Modified; 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    ViewBag.FileTypeId = new SelectList(db.FileTypes, "Id", "TypeName", dbinfo.FileTypeId); 
    return View(project); 
} 
+0

私はデータベースへの余分な往復を必要としないので、この解決策を好む –

0

使用.AsNoTracking(のためにそれらをチェックし表示するために隠された要素を追加します)比較のために元のオブジェクトを取得する.FirstOrDefault:

public ActionResult Edit(Project project) 
{ 
    if (ModelState.IsValid) 
    { 
     Project original = db.AsNoTracking().FirstOrDefault(p => p.ID == project.ID); 
     if (original.StartDate != project.StartDate || original.Duration != project.Duration) 
      doSomething(); 

     db.Entry(project).State = EntityState.Modified; 
     db.SaveChanges(); 
    } 
    return View(project); 
} 
関連する問題