swi*_*obt 8 asp.net-mvc concurrency entity-framework entity-framework-4.1
我想实现一个应用程序在此页面样本如下:http://www.asp.net/entity-framework/tutorials/handling-concurrency-with-the-entity-framework-in-an-asp-net- MVC应用程序
我有一个带有Timestamp的域类作为并发检查字段:
public class PurchaseOrder {
[Timestamp]
public byte[] Timestamp {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
在我的Edit.aspx中,我将Timestamp作为隐藏字段(我正在使用视图模型):
<%: Html.HiddenFor(model => model.PurchaseOrder.Timestamp) %>
Run Code Online (Sandbox Code Playgroud)
这是我的Edit()方法:
public ActionResult Edit(int id, FormCollection collection) {
var purchaseOrder = db.PurchaseOrders.Find(id);
UpdateModel(purchaseOrder, "PurchaseOrder", collection);
db.Entry(purchaseOrder).State = EntityState.Modified;
db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
我同时在2个独立的浏览器中打开了相同的编辑页面(这样它们的时间戳是相同的),并一个接一个地更新它们.
当我更新第二页时,我预计会出现DbUpdateConcurrencyException.但我没有.
我认为发生的是在第二页中,我在Edit操作中再次从DB获取purchaseOrder对象:
var purchaseOrder = db.PurchaseOrders.Find(id);
Run Code Online (Sandbox Code Playgroud)
因此,由于之前的编辑,时间戳是新的时间戳.
但我希望UpdateModel()从formcollection中替换Timestamp值.显然,事实并非如此.
我怎样才能检索到purchaseOrder中的时间戳的值设置为在隐藏字段,这样并发会被检测到?
它没有这种方式.通过加载实体后,Find
您无法直接更改其时间戳.原因是时间戳是计算列.EF保存每个加载实体的内部原始值和当前值.如果更改已加载实体中的值,则仅更改当前值,并且在更新期间,EF会将原始值与当前值进行比较,以了解必须更新哪些列.但是在计算列的情况下,EF不会这样做,因此永远不会使用您更改的值.
有两种解决方案.第一个是不从数据库加载实体:
public ActionResult Edit(int id, FormCollection collection)
{
// You must create purchase order without loading it, you can use model binder
var purchaseOrder = CreatePurchaseOrder(id, collection);
db.Entry(purchaseOrder).State = EntityState.Modified;
db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
第二个解决方案是在ObjectContext API的链接问题中描述的小黑客.如果您需要这个用于DbContext API,您可以尝试以下方法:
public ActionResult Edit(int id, FormCollection collection)
{
var purchaseOrder = db.PurchaseOrders.Find(id);
purchaseOrder.Timestamp = GetTimestamp(collection);
// Overwrite original values with new timestamp
context.Entry(purchaseOrder).OriginalValues.SetValues(purchaseOrder);
UpdateModel(purchaseOrder, "PurchaseOrder", collection);
db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)