查询数据库加载我的一个对象的属性,它不应该

时间:2012-04-22 17:48:43

标签: asp.net-mvc-3 entity-framework-4.1

在我的编辑控制器操作中,我发布了要更新的对象。

 [HttpPost]
 public virtual ActionResult Edit(Case myCase){
      var currentDocuments = db.CaseDocuments.Where(p => p.idCase == myCase.idCase);

            foreach (CaseDocument docInDB in currentDocuments )
            {
                var deleteDoc = true;

                foreach (CaseDocument docNew in myCase.CaseDocuments )
                {
                    if (docNew.idDocument == docInDB.idDocument)
                        deleteDoc = false;
                }
                if (deleteDoc )
                    db.CaseDocuments.Remove(docInDB);
            }

            foreach (CaseDocument pc in myCase.CaseDocuments)
            {
                if (pc.idDocument == 0)
                    db.CaseDocuments.Add(pc);
                else
                    db.Entry(pc).State = EntityState.Modified;    
            }

           *** **db.Entry(myCase).State = EntityState.Modified;**  //THIS LINE
            db.SaveChanges();
 }

Case模型的集合为Documents,它们与案例模型一起发布。

一旦我进入动作,我就可以计算集合中的文档数量,并且可以说有3个。

然后,为了查看是否需要从数据库中删除文档(因为用户从UI中删除了一个文档),我需要以这种方式从数据库中获取该案例的文档:

var currentDocuments = db.CaseDocuments.Where(p => p.idCase == myCase.idCase);

这里开始奇怪的事情:我尽快执行该语句,myCase.Documents加载了它在数据库中的内容(假设有4个)!所以,我无法比较2个集合(检测文档是否被删除并从db中删除)。

我需要的是在我的Case模型的编辑操作期间,我需要创建/更新/修改其文档。 我是否需要从其他角度看这个?我在做什么是错的?

修改 的 在评论之后,我意识到我将myCase标记为Modified的行是在开头,我想这就是这种行为的原因。

现在,将该行移到db.SaveChanges()之前,解决了这个问题,但在db.Entry(myCase).State = EntityState.Modified;说“在ObjectStateManager中已经存在一个具有相同键的对象。

我在这里做错了什么?这段代码看起来很糟糕!

1 个答案:

答案 0 :(得分:1)

以这种方式尝试:

 [HttpPost]
 public virtual ActionResult Edit(Case myCase){
     var currentDocumentIds = db.CaseDocuments
                                .Where(p => p.idCase == myCase.idCase)
                                .Select(p => p.idDocument);

     foreach (int idInDb in currentDocumentsIds.Where(i => !myCase.CaseDocuments
                                                                  .Any(ci => ci.idDocumnet == i))
     {
         var docToDelete = new CaseDocument { idDocument = idInDb };
         db.CaseDocuments.Remove(docToDelete);
     }

     foreach (CaseDocument pc in myCase.CaseDocuments)
     {
         if (pc.idDocument == 0)
            db.CaseDocuments.Add(pc);
         else
            db.Entry(pc).State = EntityState.Modified;    
     }

     db.Entry(myCase).State = EntityState.Modified;
     db.SaveChanges();
}

编辑:此代码与您的代码之间的区别在于它如何与现有文档一起使用。它不加载它们 - 它只加载它们的ID。这样您就可以从数据库中保存一些数据传输,但它也可以帮助您避免该异常。从数据库加载文档时,您已将文档附加到上下文中,但如果您尝试调用它:

db.Entry(pc).State = EntityState.Modified; 

您将尝试使用相同的键将文档的另一个实例附加到上下文。这是不允许的 - 上下文只能附加具有唯一键的单个实例。