HttpPost ASP MVC上的ConcurrencyException

时间:2019-03-11 21:51:14

标签: c# asp.net asp.net-mvc entity-framework

您好,我正在尝试在db中编辑我的表,并给我此错误存储中的更新,插入或删除指令影响了意外的行数(0)。自加载以来,实体可能已被修改或删除。

  

尝试许多测试,当我到达SaveChange时停止过程   和不完整的操作

     

这是实现

public ActionResult Edit(int? id)
        {
            db = new IdentityDBEntities();
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Article article = db.Articles.Find(id);
            if (article == null)
            {
                return HttpNotFound();
            }
            ViewBag.Idc = new SelectList(db.Categories, "Id", "libelle", article.Idc);

            return View(article);
        }

        // POST: Articles/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Ida,description,UserId,Idc,titre,image")] Article article, HttpPostedFileBase image)
        {

            if (ModelState.IsValid)
            {
                if (image != null)
                {
                    article.image = image.FileName;
                }
                db = new IdentityDBEntities();
                article.UserId = System.Web.HttpContext.Current.User.Identity.GetUserId();
                db.Entry(article).State = EntityState.Modified;
                db.SaveChanges(); 


                return RedirectToAction("Index");
            }
            ViewBag.Idc = new SelectList(db.Categories, "Id", "libelle", article.Idc);

            return View(article);
        }

1 个答案:

答案 0 :(得分:0)

文章已加载到DbContext的一个实例中,而您试图将其保存到另一个实例中。该实体在保存之前需要与新上下文关联。 (即AttachUpdate)但是,我不推荐这种方法。

作为一般规则,您应该避免将实体与Web客户端之间来回传递。如果您接受Web客户端的实体,则很简单的事情就是找到将已修改的实体传递给服务器的调用,应用断点,并在继续之前使用调试器修改内容。如果服务器仅将实体附加到上下文并保存更改,则可以按照应用程序不允许的方式修改数据。它还需要向客户端发送/从客户端发送比通常所需更多的信息。

您还遇到了一个问题,即在读取数据到准备更新数据之间,当前会话中某一时刻支持实体的数据已被另一会话修改。系统不应仅在未首先(通过时间戳或最后修改的日期/时间)验证自加载实体以来尚未更新数据的情况下附加和覆盖数据。系统可以从那里采取适当的措施。 (记录数据将被覆盖,覆盖或合并,并通知用户查看其更改。)

编辑:概述一个例子。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Ida,description,UserId,Idc,titre,image")] Article article, HttpPostedFileBase image)
{
    if (!ModelState.IsValid)
    {
        ViewBag.Idc = new SelectList(db.Categories, "Id", "libelle", article.Idc);
        return View(article); 
    }

    using (var db = new IdentityDBEntities())
    {
        var existingArticle = db.Articles.Single(x => x.ArticleId == article.ArticleId);
        if (existingArticle.RowVersion != article.RowVersion) // Or compare LastModifiedDateTime etc.
        {
            // Set a validation state to tell the user that the article had changed since they started editing. Perhaps merge values across, but send the article back.
            return View(existingArticle);
        }

        if (image != null)
            existingArticle.image = image.FileName;

        existingArticle.UserId = System.Web.HttpContext.Current.User.Identity.GetUserId(); // can this be updated?
        db.SaveChanges(); 
    }
    return RedirectToAction("Index");
}

主要区别: DbContext是一次性的,因此应包装在using块中。 我们从上下文中加载该文章,请检查它是否已被修改,因为我们最初已加载它。 (为确保用户可以修改本文,还需要进行其他验证检查,这也是审慎的选择),如果它不是过时且有效的话,请在各个字段之间进行转移并保存更改。