2011-11-04 69 views
0

我有一个代码优先EF 4.1模型看起来像这样:EF 4 - MVC3:保存复杂对象图(嵌套一个一对多关系)

http://pct.staging.xeed.nl/images/model.png

该模型的目的是序列化到使用jQuery在浏览器中处理JSON。在jQuery中,这个对象图被实例化为一个Javascript对象。用户交互(添加/删除操作以及添加/删除任务)会导致Javascript对象的修改。当一个新的任务或动作对象被添加到图中时,它将得到ID = 0.当一个任务或动作对象被删除时,它将得到ui_status =“deleted”。在用户界面中保存事件后,修改的Javascript对象被序列化为JSON并发送到“AssignmentController”。

我的问题是,我不知道什么是处理保存这个对象图的最佳方法。 (1)'不允许添加与处于已删除状态的实体的关系'或(2)'具有相同关键字的对象已经存在于ObjectStateManager'中。

(ad 1) - 尝试从任务中删除操作时出现此错误。

(ad 2) - 试图一次保存2个或更多新对象时出现此错误。新对象都有ID = 0,这可能是导致此错误的原因。

这里是我的代码:

 // POST: /Assignment/Save/assignment 
    [HttpPost] 
    public string Save([Bind(Exclude="date")] Assignment assignment) 
    { 
     string message; 

     assignment.date = DateTime.Now; 
     Session["currentAssignment"] = assignment; 

     if (!User.Identity.IsAuthenticated) 
     { 
      return "Please Log in first."; 
     } 

     if (ModelState.IsValid) 
     { 
      assignment.username = User.Identity.Name; 

      if (assignment.tasks != null) 
      { 
       foreach (var task in assignment.tasks.ToList()) 
       { 
        db.Tasks.Attach(task); 

        if (task.actions != null) 
        { 
         foreach (var action in task.actions.ToList()) 
         { 
          db.Actions.Attach(action); 

          if ((task.ui_status == "deleted" || action.ui_status == "deleted")) 
          { 
           if (action.actionID > 0) 
           { 
            db.Entry(action).State = EntityState.Deleted; 

           } 
           else 
           { //object was deleted from a new object graph 
            //just save it with ui_status="deleted", it will be deleted from the db next time around 
           } 
          } 
          else if (action.actionID == 0) 
          { 
           db.Entry(action).State = EntityState.Added; 
          } 
          else 
          { 
           db.Entry(action).State = EntityState.Modified; 
          } 

         } 
        } 

        if (task.ui_status == "deleted") 
        { 
         if (task.taskID > 0) 
         { 
          db.Entry(task).State = EntityState.Deleted; 
         } 
         else 
         { //object was deleted from a new object graph 
          //just save it with ui_status="deleted", it will be deleted from the db next time around 
         } 
        } 
        else if (task.taskID== 0) 
        { 
         db.Entry(task).State = EntityState.Added; 
        } 
        else 
        { 
         db.Entry(task).State = EntityState.Modified; 
        } 

       } 
      } 

      db.Assignments.Attach(assignment); 
      db.Entry(assignment).State = assignment.assignmentID == 0 ? EntityState.Added : EntityState.Modified; 
      db.SaveChanges(); 

      return js.Serialize(assignment); 
     } 
    } 

我一直在为此而努力,而现在,看了所有的职位。我会认为EF会照顾这样的事情,因为大多数不重要的应用程序都会遇到这种情况。

对此的任何想法将不胜感激。

+0

如果你解决了这个问题,你应该把它作为你自己问题的答案贴出来,然后接受它,这样人们就不会试图回答这个问题,也不会让每个人更清楚解决方案。 – Joakim

+0

很对,对不起 –

回答

1

自己管理解决问题。我首先通过为每个对象设置EntityState.Added /EntityState.Modified来更新对象图。然后我调用db.SaveChanges()并再次运行所有对象以在需要时设置EntityState.Deleted。然后我再次调用db.SaveChanges()。

这里是代码:

 [HttpPost] 
    public string Save([Bind(Exclude="date")] Assignment assignment) 
    { 
     string message; 

     assignment.date = DateTime.Now; 
     Session["currentAssignment"] = assignment; 

     if (!User.Identity.IsAuthenticated) 
     { 
      return "Please Log in first."; 
     } 

     if (ModelState.IsValid) 
     { 
      assignment.username = User.Identity.Name; 

      if (assignment.tasks != null) 
      { 
       foreach (var task in assignment.tasks.ToList()) 
       { 
        if (task.actions != null) 
        { 
         foreach (var action in task.actions.ToList()) 
         { 
          db.Entry(action).State = action.actionID == 0 ? EntityState.Added : EntityState.Modified; 
         } 
        } 
        db.Entry(task).State = task.taskID == 0 ? EntityState.Added : EntityState.Modified; 
       } 
      } 

      db.Entry(assignment).State = assignment.assignmentID == 0 ? EntityState.Added : EntityState.Modified; 
      db.SaveChanges(); 

      if (assignment.tasks != null) 
      { 
       foreach (var task in assignment.tasks.ToList()) 
       { 
        if (task.actions != null) 
        { 
         foreach (var action in task.actions.ToList()) 
         { 
          if ((task.ui_status == "deleted" || action.ui_status == "deleted")) 
          { 
           db.Entry(action).State = EntityState.Deleted; 
          } 
         } 
        } 
        if (task.ui_status == "deleted") 
        { 
         db.Entry(task).State = EntityState.Deleted; 
        } 
       } 
      } 
      db.SaveChanges(); 

      return js.Serialize(assignment); 
     } 

希望这有助于任何人跑进今后发生类似的问题。