ASP.NET MVC - 附加类型“MODELNAME”的实体失败,因为同一类型的另一个实体具有相同的主键值 [英] ASP.NET MVC - Attaching an entity of type 'MODELNAME' failed because another entity of the same type already has the same primary key value

查看:969
本文介绍了ASP.NET MVC - 附加类型“MODELNAME”的实体失败,因为同一类型的另一个实体具有相同的主键值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之,POSTING包装器模型中抛出异常,并将一个条目的状态更改为Modified。在更改状态之前,状态设置为'Detached',但调用Attach()确实引发相同的错误。我正在使用EF6。

In a nutshell the exception is thrown during POSTing wrapper model and changing the state of one entry to 'Modified'. Before changing the state, the state is set to 'Detached' but calling Attach() does throw the same error. I'm using EF6.

请找到我的代码(型号名称已更改,以便于阅读)

Please find my code below(model names have been changed to make it easier to read)

模型

// Wrapper classes
        public class AViewModel
        {
            public A a { get; set; }
            public List<B> b { get; set; }
            public C c { get; set; }
        }   

控制器

        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            if (!canUserAccessA(id.Value))
                return new HttpStatusCodeResult(HttpStatusCode.Forbidden);

            var aViewModel = new AViewModel();
            aViewModel.A = db.As.Find(id);

            if (aViewModel.Receipt == null)
            {
                return HttpNotFound();
            }

            aViewModel.b = db.Bs.Where(x => x.aID == id.Value).ToList();
            aViewModel.Vendor = db.Cs.Where(x => x.cID == aViewModel.a.cID).FirstOrDefault();

            return View(aViewModel);
        }

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(AViewModel aViewModel)
        {
            if (!canUserAccessA(aViewModel.a.aID) || aViewModel.a.UserID != WebSecurity.GetUserId(User.Identity.Name))
                return new HttpStatusCodeResult(HttpStatusCode.Forbidden);

            if (ModelState.IsValid)
            {
                db.Entry(aViewModel.a).State = EntityState.Modified; //THIS IS WHERE THE ERROR IS BEING THROWN
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(aViewModel);
        }

如上图所示

db.Entry(aViewModel.a).State = EntityState.Modified;

抛出异常:


连接类型A的实体失败,因为
相同类型的另一个实体已经具有相同的主键值。当
使用'附加'方法或将实体的状态设置为
'Unchanged'或'Modified'时,如果图中的任何实体具有
冲突的键值,则可能会发生这种情况。这可能是因为一些实体是新的,并且
尚未收到数据库生成的键值。在这种情况下,使用
添加方法或添加实体状态来跟踪图形,
然后将非新实体的状态设置为不变或修改为
适当的。

Attaching an entity of type 'A' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

有人在我的代码中看到任何错误,或者在编辑模型时会在什么情况下抛出这样的错误呢? / p>

Does anybody see anything wrong in my code or understand in what circumstances it would throw such error during editing a model?

推荐答案

问题SOLVED!

/ code>方法可能有助于某人,但在这种情况下不会有帮助,因为在编辑GET控制器功能中加载文档时已经被跟踪。附件会抛出完全相同的错误。

Attach method could potentially help somebody but it wouldn't help in this situation as the document was already being tracked while being loaded in Edit GET controller function. Attach would throw exactly the same error.

我在这里遇到的问题是由函数 canUserAccessA() A实体在更新对象状态之前a。这正在修复跟踪的实体,它正在将对象的状态更改为 Detached

The issue I encounter here was caused by function canUserAccessA() which loads the A entity before updating the state of object a. This was screwing up the tracked entity and it was changing state of a object to Detached.

解决方案是修改 canUserAccessA(),以使我正在加载的对象不被跟踪。

The solution was to amend canUserAccessA() so that the object I was loading wouldn't be tracked. Function AsNoTracking() should be called while querying the context.

// User -> Receipt validation
private bool canUserAccessA(int aID)
{
    int userID = WebSecurity.GetUserId(User.Identity.Name);
    int aFound = db.Model.AsNoTracking().Where(x => x.aID == aID && x.UserID==userID).Count();

    return (aFound > 0); //if aFound > 0, then return true, else return false.
}

由于某种原因,我无法使用 .Find(aID ) AsNoTracking()但它并不重要,因为我可以通过更改查询实现相同。

For some reason I couldnt use .Find(aID) with AsNoTracking() but it doesn't really matter as I could achieve the same by changing the query.

希望这将有助于任何有类似问题的人!

Hope this will help anybody with similar problem!

这篇关于ASP.NET MVC - 附加类型“MODELNAME”的实体失败,因为同一类型的另一个实体具有相同的主键值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆