【问题标题】:Exception thrown with Entity Framework adding new row to the DB实体框架向数据库添加新行时引发异常
【发布时间】:2011-10-06 17:13:06
【问题描述】:

我一直在尝试调试它并以不同的方式表达我想要做的事情,但没有运气。我对实体框架知之甚少,而且我从另一个不再存在的开发人员那里继承了这段代码,所以我对模型知之甚少。也许有人至少可以让我指出正确的方向。这是我的代码:

//Append note to project notes too
task.TPM_PROJECTVERSIONReference.Load();
TPM_PROJECTVERSIONNOTES newNote = new TPM_PROJECTVERSIONNOTES();
newNote.TS = System.DateTime.Now;
newNote.TPM_USER = SessionHandler.LoginUser;
newNote.NOTES = task.NOTES;
newNote.PROJECTID = this.ProjectId;
newNote.VERSIONID = this.VersionId;
task.TPM_PROJECTVERSION.TPM_PROJECTVERSIONNOTES.Add(newNote); //<-- Exception

我有“任务”,它指向它所属的项目版本。这些项目有很多笔记。我想在任务的项目中添加一个新注释。但是,我在最后一行遇到异常:

System.InvalidOperationException 未被用户代码处理
Message=两个对象之间的关系不能 定义是因为它们附加到不同的 ObjectContext 对象。
Source=System.Data.Entity

这似乎应该是一件非常简单的事情。这不是正确的方法吗?谢谢!

编辑:

好的,我已经从函数中删除了所有其他代码并创建了一个全新的上下文。这是现在从头到尾的整个函数:

//Append note to project notes too
using (TPMEntities context = new TPMEntities(General.EntityName()))
{
   TPM_PROJECTVERSIONNOTES newNote = context.TPM_PROJECTVERSIONNOTES.CreateObject();
   newNote.TS = System.DateTime.Now;
   newNote.TPM_USER = SessionHandler.LoginUser;
   newNote.NOTES = this.txtTaskNotes.Text;
   TPM_PROJECTVERSION version = (from pv in context.TPM_PROJECTVERSION
                                 where pv.PROJECTID == this.ProjectId && pv.VERSIONID == this.VersionId
                                 select pv).First();

   version.TPM_PROJECTVERSIONNOTES.Add(newNote);
   context.SaveChanges();
}

不过,我还是遇到了同样的异常:

System.InvalidOperationException was unhandled by user code
  Message=The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.
  Source=System.Data.Entity

我简直无法理解怎么会有两种情况?我在代码中的每个地方都使用“上下文”。实体框架如何让简单地将单行添加到我的数据库中变得如此困难?

【问题讨论】:

    标签: c# .net asp.net entity-framework


    【解决方案1】:

    问题出在

    newNote.TPM_USER = SessionHandler.LoginUser;
    

    LoginUser 是使用另一个上下文创建的。您将其附加到context。有几种方法可以解决这个问题。

    LoginUser 从它创建的上下文中分离出来。

    sessionContext.Detach(SessionHandler.LoginUser);
    

    然后在你的方法里面

    using (TPMEntities context = new TPMEntities(General.EntityName()))
    {
       context.Attach(SessionHandler.LoginUser);
    
       TPM_PROJECTVERSIONNOTES newNote = context.TPM_PROJECTVERSIONNOTES.CreateObject();
       newNote.TS = System.DateTime.Now;
       newNote.TPM_USER = SessionHandler.LoginUser;
       newNote.NOTES = this.txtTaskNotes.Text;
       TPM_PROJECTVERSION version = (from pv in context.TPM_PROJECTVERSION
                                     where pv.PROJECTID == this.ProjectId && pv.VERSIONID == this.VersionId
                                     select pv).First();
    
       version.TPM_PROJECTVERSIONNOTES.Add(newNote);
       context.SaveChanges();
    }
    

    或者如果你已经映射了标量外键属性newNote.TPM_USER_ID

    using (TPMEntities context = new TPMEntities(General.EntityName()))
    {
       TPM_PROJECTVERSIONNOTES newNote = context.TPM_PROJECTVERSIONNOTES.CreateObject();
       newNote.TS = System.DateTime.Now;
       newNote.TPM_USER_ID = SessionHandler.LoginUser.ID;
       newNote.NOTES = this.txtTaskNotes.Text;
       TPM_PROJECTVERSION version = (from pv in context.TPM_PROJECTVERSION
                                     where pv.PROJECTID == this.ProjectId && pv.VERSIONID == this.VersionId
                                     select pv).First();
    
       version.TPM_PROJECTVERSIONNOTES.Add(newNote);
       context.SaveChanges();
    }
    

    【讨论】:

      【解决方案2】:

      尝试将您的 Web.Config 连接字符串设置为包含 MultipleActiveResultSets=True。

      【讨论】:

      • 那你的理由是什么?这是因为我正在对“任务”进行大量编辑,而我不能同时向它添加新关系吗?
      • 啊...不使用 MS SQL。我遇到了类似的问题,并进行了更改修复了它。不确定 EF 究竟如何处理数据库事务,但我知道它必须处理多个结果集才能维护它的 OO 方法。我通常将 DB 上下文加载为模块级变量并在整个类中使用它,因此我不会遇到多个上下文对象的问题。 (注意:有时您需要多个上下文)。
      • 是的,这段代码发生在创建上下文的 using() 块中。有/应该/只有一个上下文..
      • “任务”是在 using() 块的内部、外部还是作为参数定义的?
      • 并非如此。任务在 using 块中声明,但我们使用函数加载它:task = TaskManager.GetTaskIfExists(context, this.TaskId); -- 但是,该函数使用相同的上下文并执行 LINQ 查询以从数据库加载 TPM_TASK 对象。既然传入了上下文,那应该没问题吧?
      【解决方案3】:

      Welp 经过近 4 个小时的尝试,我唯一能真正开始工作的解决方案就是这个。显然,将新数据插入数据库是 Entity Framework 的一项高级功能,需要深入了解其内部工作原理。

      context.ExecuteStoreQuery<object>("INSERT INTO TPM_PROJECTVERSIONNOTES (NOTES, PROJECTID, VERSIONID, USERID, TS) VALUES (:notes, :projId, :versionId, :userId, :timestamp)",
         new OracleParameter("notes", this.txtTaskNotes.Text),
         new OracleParameter("projId", this.ProjectId),
         new OracleParameter("versionId", this.VersionId),
         new OracleParameter("userId", SessionHandler.LoginUser.USERID),
         new OracleParameter("timestamp", DateTime.Now));
      

      哦,好吧,至少它很快。

      【讨论】:

        猜你喜欢
        • 2011-04-01
        • 1970-01-01
        • 2018-08-24
        • 2016-06-18
        • 2017-07-31
        • 2016-12-27
        • 2023-03-08
        • 1970-01-01
        • 2018-09-13
        相关资源
        最近更新 更多