当前位置:  开发笔记 > 后端 > 正文

编辑操作中使用RowVersion的ASP.NET MVC并发

如何解决《编辑操作中使用RowVersion的ASP.NETMVC并发》经验,为你挑选了2个好方法。

我想为我们的问题跟踪应用程序做一个简单的编辑表单.为简单起见,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我编辑的对象正确地处理到上下文?

提前致谢



1> Craig Stuntz..:

你在做什么是棘手的,但可以使其工作.让我们假设您的时间戳字段被调用ConcurrencyToken.显然,您必须在视图中包含此值并将其与表单一起提交.但是您不能简单地将其分配给thisIssue.ConcurrencyTokenPOST中的值,因为EF将记住"旧"值(您通过调用从DB获取的值Single()以及"新"值(来自您的表单)并使用WHERE子句中的"旧"值.所以你需要骗取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两次来优化它,但这应该让你开始.



2> Carl G..:

下面是使用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;
}

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有