0

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

 [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 个)!因此,我无法比较这两个集合(以检测文档是否被删除并将其从数据库中删除)。

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

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

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

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

4

1 回答 1

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; 

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

于 2012-04-23T10:44:05.473 回答