我正致力於捕獲併發異常。我能夠在用戶編輯好數據時捕獲併發異常。我在用戶刪除數據時遇到了異常。ViewModel刪除併發Excecption不起作用
在我的索引頁面上,我有一個按鈕來刪除每個車輛對象。按下該按鈕將執行Delete(刪除)操作Post。這裏是刪除操作:
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(VehicleIndexViewModel vehicleIndexViewModel)
{
try
{
Vehicle vehicle = db.Vehicles.Find(vehicleIndexViewModel.VehicleID);
//To test for concurrency errors
//vehicle.Timestamp = vehicleIndexViewModel.Timestamp;
db.Entry(vehicle).State = EntityState.Deleted;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DbUpdateConcurrencyException)
{
return RedirectToAction("Index",
new System.Web.Routing.RouteValueDictionary{{"concurrencyError", true }});
}
catch (DataException)
{
//Log the error (add a variable name after Exception)
ModelState.AddModelError(string.Empty, "The system was unable to delete that"
+ " vehicle. Try again, and if the problem persists"
+ " contact your system administrator.");
return RedirectToAction("Index");
}
}
無論如何,用戶應該被重定向到索引頁面。這裏是索引頁的獲取行動:
public ViewResult Index(bool? concurrencyError)
{
if (concurrencyError.GetValueOrDefault())
{
ViewBag.ConcurrencyErrorMessage = "The record you attempted to delete "
+ "was modified by another user after you got the original values. "
+ "The delete operation was canceled and the current values in the "
+ "database have been displayed. If you still want to delete this "
+ "record, click the Delete button again. Otherwise "
+ "click the Back to List hyperlink.";
}
IEnumerable<Vehicle> vehicles = db.Vehicles.Include(v => v.VehicleType);
IEnumerable<VehicleIndexViewModel> viewModel
= Mapper.Map<IEnumerable<Vehicle>,
IEnumerable<VehicleIndexViewModel>>(vehicles);
return View(viewModel);
}
的代碼永遠不會捕捉併發性錯誤。我通過兩次打開索引頁來測試。在其中一頁上,我打開車輛的編輯頁面並改變一些內容。保存完成後,我會回到其他頁面並點擊「刪除」。 刪除操作被觸發,車輛被刪除,但併發錯誤未被捕獲。你可以看到我在哪裏註釋vehicle.Timestamp = vehicleIndexViewModel.Timestamp ;.我認爲將viewModel的值放回到實際中會引起錯誤,但它也不會以這種方式工作。
我敢肯定,這只是我不明白的,但是我做錯了什麼?
編輯
埃裏克飛利浦發現,我有邏輯錯誤,但是,我遇到了馬上另一個問題。我的ViewModel沒有返回Timestamp數據。事實上,它返回的唯一數據是VehicleID。
當我試圖向表單添加一個隱藏字段時,會出現錯誤。下面的代碼將不起作用:
<input type="hidden" name="Timestamp" value="@item"/>
時間戳字段需要是有效的Base-64字符串。你將得到的錯誤是:
輸入不是一個有效的Base-64字符串,因爲它包含非基本填充中最多64個字符,超過>雙填充字符,或一個非空白字符字符。
這是我如何結束存儲視圖上的時間戳值:
<input type="hidden" name="Timestamp" value="@Convert.ToBase64String(item.Timestamp)"/>
所以,我的整個Html.BeginForm看起來是這樣的:
@using (Html.BeginForm("Delete", "Vehicle", FormMethod.Post, null))
{
<input type="hidden" name="VehicleID" value="@item.VehicleID"/>
<input type="hidden" name="VehicleName" value="@item.VehicleName"/>
<input type="hidden" name="Timestamp" value="@Convert.ToBase64String(item.Timestamp)"/>
<input type="image" src="../../Content/Images/Delete.gif" value="Delete" name="deletevehicle @item.VehicleID" onclick="return confirm('Are you sure you want to delete @item.VehicleName.Replace("'", "").Replace("\"", "")?');"/>
}
雖然,我真的沒不需要將VehicleName放在隱藏字段中。
一旦完成,我需要做的就是使用AutoMapper將值映射回車對象,將EntityState設置爲Deleted,然後嘗試SaveChanges;
try
{
Vehicle vehicle = Mapper.Map<VehicleIndexViewModel, Vehicle>(vehicleIndexViewModel);
db.Entry(vehicle).State = EntityState.Deleted;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (DbUpdateConcurrencyException)
{
return RedirectToAction("Index", new System.Web.Routing.RouteValueDictionary { { "concurrencyError", true } });
}
就是這樣!
但在這種情況下,它允許有人快速雙擊,因此兩個潛在負載和重複刪除。 – 2012-04-03 02:27:15
謝謝!這是我遇到的多個問題的開始。我將在下面回答其餘問題。 – user1304444 2012-04-03 03:08:25