[英]creating a create/edit view/action with SelectList in asp.net mvc
[英]ASP.NET MVC Concurrency with RowVersion in Edit Action
我想为我们的问题跟踪应用程序做一个简单的编辑表单。 为简单起见,HttpGet Edit操作看起来像这样:
// Issues/Edit/12
public ActionResult Edit(int id)
{
var thisIssue = edmx.Issues.First(i => i.IssueID == id);
return View(thisIssue);
}
然后HttpPost动作看起来像这样:
[HttpPost]
public ActionResult Edit(int id, FormCollection form)
{
// this is the dumb part where I grab the object before I update it.
// concurrency is sidestepped here.
var thisIssue = edmx.Issues.Single(c => c.IssueID == id);
TryUpdateModel(thisIssue);
if (ModelState.IsValid)
{
edmx.SaveChanges();
TempData["message"] = string.Format("Issue #{0} successfully modified.", id);
return RedirectToAction("Index");
}
return View(thisIssue);
}
这非常有效。 但是,并发检查不起作用,因为在Post中,我正在尝试更新它之前重新检索当前实体。 但是,使用EF,我不知道如何使用SaveChanges()
但将thisIssue
附加到上下文中。 我试着打电话给edmx.Issues.Attach(thisIssue)
但我得到了
The object cannot be attached because it is already in the object context. An object can only be reattached when it is in an unchanged state.
如何使用EF处理MVC中的并发和/或如何Attach
我编辑的对象正确Attach
到上下文?
提前致谢
你在做什么是棘手的,但可以使其工作。 让我们假设你的timestamp字段叫做ConcurrencyToken
。 显然,您必须在视图中包含此值并将其与表单一起提交。 但是你不能简单地将它分配给POST中thisIssue.ConcurrencyToken
的值,因为EF将记住“旧”值(你通过调用Single()
从DB获取的值以及“new” “value(来自您的表单)并使用WHERE
子句中的”old“值。因此您需要骗取EF并指定正确的值。请尝试以下操作:
var thisIssue = edmx.Issues.Single(c => c.IssueID == id);
TryUpdateModel(thisIssue); // assign ConcurrencyToken
var ose = Context.ObjectStateManager.GetObjectStateEntry(entityToUpdate);
ose.AcceptChanges(); // pretend object is unchanged
TryUpdateModel(thisIssue); // assign rest of properties
您可以通过仅绑定ConcurrencyToken
而不是两次调用TryUpdateModel
来优化此操作,但这应该可以帮助您入门。
下面是使用EF5执行乐观并发兼容更新的示例(该方法来自存储库。)假设实体使用[ConcurrencyCheck]
定义时间戳。 调用DbContext.SaveChanges()
时会发生并发异常。
public TEntity Update(TEntity entity)
{
var attached = this.GetById(entity.Id);
if (attached == null)
{
throw new MvcBootstrapDataException("{0} with Id = {1} does not exist.".F(typeof(TEntity).Description(), entity.Id));
}
var entry = this.Context.Entry(attached);
// The Timestamp must be in the original values for optimistic concurrency checking to occur.
// Otherwise the context knows that the Timestamp has been modified in the context
entry.OriginalValues["Timestamp"] = entity.Timestamp;
entry.CurrentValues.SetValues(entity);
attached.Modified = DateTime.Now;
return attached;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.