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

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

问题描述

在简而言之异常正在发布的包装模式,改变一个进入修改的状态时抛出。改变前的状态,状态设置为独立式,但调用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.

请在下面找到我的code(型号名称已被更改,使其更易于阅读)

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'失败,因为的另一个实体
  同类型已经有相同的主键值。发生这种情况时,
  使用连接的方法,或一个实体的状态设置为
  '不变'或'修改',如果图中的任何实体具有
  冲突的键值。这可能是因为一些实体是新的和
  尚未收到数据库生成的键值。在这种情况下使用
  添加方法或添加实体状态跟踪图和
  然后将非新实体的状态为未改变或修饰的作为
  合适的。

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.

有谁看到什么错在我的code或在什么情况下理解编辑模式中会抛出这样的错误?

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

推荐答案

问题解决了!

Attach方法可能会帮助别人,但难道不在这种情况下帮助作为文档的对象是在编辑中加载GET控制器的功能正在被跟踪已。附上会抛出一模一样的错误。

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

我在这里遇到的问题是由加载一个实体​​更新对象的状态之前功能canUserAccessA()引起的。这是搞砸了跟踪的实体,它改变对象的状态为'分离'。

The issue I encounter here was caused by function canUserAccessA() which loads 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(),所以,我是装的对象将无法被追踪。功能AsNoTracking()应该是召唤,而查询的上下文。

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

// User -> Receipt validation
private bool canUserAccessA(int aID)
{
    int userID = WebSecurity.GetUserId(User.Identity.Name);
    int aFound = db.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 doesnt really matter as I could achieve the same by changing the query.

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

Hope this will help anybody with similar problem!

问候,
克里斯

Regards, Chris

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

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