2013-05-22 22 views
6

我有或多或少的標準看型號:檢測模型屬性的狀態變化,控制器,使用實體框架

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

我相信你可以從數據庫中的原始一個讀取比較編輯的實體。

喜歡的東西:

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

我alreadey試過這種跟蹤多個目標。我收到以下錯誤: 'ObjectStateManager中已存在具有相同鍵的對象。 ObjectStateManager不能使用同一個鍵跟蹤多個對象。 描述:執行當前Web請求期間發生未處理的異常。請查看堆棧跟蹤以獲取有關該錯誤的更多信息以及源代碼的位置。 異常詳細信息:System.InvalidOperationException:具有相同鍵的對象已存在於ObjectStateManager中。 ObjectStateManager無法使用相同的密鑰跟蹤多個對象。' – Chopo87

+0

有無'db.Entry(original).State = EntityState.Modified;'? –

+0

好點,讓我試試看 – Chopo87

2

如果你想這樣做,不詢問你的持久化層我猜想將舊值模型中的字段,然後讓他們在頁面隱藏字段是解決這個最簡單的方法。

所以加CurrentStartDate和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; } 
} 

,然後用舊值在視圖中添加隱藏字段:

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

這會給你的東西比較選擇值在您的控制器操作中。

+1

其實我寧願做控制器內的所有檢查,如果可能的話,保持代碼清潔。你可以擴展如何「查詢你的持久層」,這聽起來像我想要實現的。 – Chopo87

+1

然後你有來從你的數據庫的當前項目並檢查舊值,並比較你是從客戶端得到的值。 – KMan

+1

我已經試過了:我得到以下異常:ObjectStateManager中已存在具有相同鍵的對象。該ObjectStateManager不能用相同的key.' – Chopo87

6

您可以通過ViewBag賬面原值解決它。

在行動:

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