更新共享多对多关系的多个记录失败

时间:2013-09-23 20:53:18

标签: c# entity-framework dbcontext

详细

我有2个表(程序,外科医生)和一个查找表(ProcSurg)来创建多对多的关系。

scar_Requests       scar_Procedures        scar_ProcSurg            scar_Surgeons
-------------       ---------------        -------------            -------------
RequestID      <>   ProcedureID       <>   ProcedureID(fk)   <>     SurgeonID
...                 RequestID              SurgeonID(fk)            ...
                    ...

单个请求可以有多个程序,每个程序可以有多个外科医生。

一切都保存正确,直到我有两个共享同一个外科医生的程序。

Error: InvalidOperationException was unhandled
The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects.

我将保存此部分记录的代码分离出来,试图找出我的问题..

Addprocedures是一个包含1个过程和外科医生列表的类

class Procedure
{
    public scar_Procedures Procedure { get; set; }
    public List<scar_Surgeons> Surgeons { get; set; }

    public void RemoveSurgeon(int SurgeonID)
    {
        Surgeons.Remove(Surgeons.Where(x => x.SurgeonID == SurgeonID).FirstOrDefault());
    }

    public Procedure()
    {
        Surgeons = new List<scar_Surgeons>();
    }
}

保存代码:使用DBContext

    private void SaveProcSurg()
    {
        using (MCASURGContext db2 = new MCASURGContext())
        {
            foreach (Procedure p in AddProcedures)
            {
                if (p.Procedure.RequestID == 0)
                {
                    p.Procedure.RequestID = ReqID;
                }

                p.Procedure.scar_Surgeons.Clear();

                foreach (scar_Surgeons s in p.Surgeons)
                {
                    if (db2.ChangeTracker.Entries<scar_Surgeons>().Where(x => x.Entity.SurgeonID == s.SurgeonID).FirstOrDefault() == null)
                    {
                        db2.scar_Surgeons.Attach(s);
                    }
                    p.Procedure.scar_Surgeons.Add(s);
                }

                if (p.Procedure.ProcedureID == 0)
                {
                    db2.scar_Procedures.Add(p.Procedure);
                    db2.Entry(p.Procedure).State = System.Data.Entity.EntityState.Added;
                }
                else
                {
                    db2.scar_Procedures.Attach(p.Procedure);
                    db2.Entry(p.Procedure).State = System.Data.Entity.EntityState.Modified;
                }
            }
            db2.SaveChanges();
        }

    }

我尝试了几种保存记录的方法,这是我最接近正确的方法。

我觉得这与我将外科医生连接到实体然后再附加到手术的方式有关。关于我能找到答案的任何帮助,想法或建议都会很棒!

我一直在无休止地搜索谷歌超过一个星期,我一直在试图围绕实体框架正在做什么,但我仍然很新。

2013年9月24日编辑

很抱歉,这是评论部分的完整代码段,其中包含req变量

 //Internal variable
 private scar_Requests req;
 private List<Procedure> AddProcedures = new List<Procedure>();

 //Gets a scar_Request from the DB
    private void GetRequest()
    {
        using (MCASURGContext db = new MCASURGContext())
        {
            req = db.scar_Requests.Include("scar_Procedures.scar_Surgeons").Include("scar_Status").Include("scar_Users.scar_Service").Where(x => x.RequestID == ReqID).FirstOrDefault();

            foreach (scar_Procedures p in req.scar_Procedures) { AddProcedures.Add(new Procedure() { Proc = p, Surgeons = p.scar_Surgeons.ToList() }); }
        }
}

1 个答案:

答案 0 :(得分:0)

保持良好状态我会发布我的回答,因为我认为我已经弄明白了。也许它会在将来帮助某人。

我完全重写了保存并删除了之前使用过的许多无用的代码,并减少了对DB的调用。还有其他方法我没有在上面发布,保存了我压缩成单一方法的记录的其他部分。

基本上我从DB获取记录及其连接表,并遍历需要更新的所有字段/连接表并将其保存回数据库。 (现在看起来非常明显,但我以前尝试过这种方式而且我一定有错误,因为我这样做的前几次没有工作。)

我不知道它的100%是否正确或是否符合正常的编码标准,并且在完成之前我还有一些最后的调整要做。

    private void SaveProcSurg()
    {
        using (MCASURGContext db2 = new MCASURGContext())
        {

            //Get Record from DB
            scar_Requests sReq = db2.scar_Requests.Include("scar_Users").Include("scar_Status").Include("scar_Procedures.scar_Surgeons").Where(x => x.RequestID == ReqID).FirstOrDefault();

            //Update Record fields
            sReq.CreationDate = req.CreationDate == null ? DateTime.Now : req.CreationDate = req.CreationDate;
            sReq.DateOfSurgery = dtpDateOfSurgery.Value;
            sReq.IsDeleted = false;
            sReq.IsScheduled = false;
            sReq.LatexAllergy = cbLatexAllergy.Checked;
            sReq.ModifiedDate = DateTime.Now;
            sReq.MRN = txtMRN.Text;
            sReq.PatientName = txtPatientName.Text;
            foreach (RadioButton rb in gbPatientType.Controls) if (rb.Checked == true) sReq.PatientType = rb.Text;
            sReq.PreOpDiagnosis = txtPreOpDiag.Text;
            sReq.PrimarySurgeon = txtPrimarySurgeon.Text;
            sReq.PrivateComment = txtPrivateComment.Text;
            sReq.PublicComment = txtPublicComment.Text;
            sReq.RequestID = ReqID;
            sReq.StatusID = req.StatusID;
            sReq.UserID = req.UserID;

            //Update Users/Status
            sReq.scar_Users = db2.scar_Users.Where(x => x.UserID == sReq.UserID).FirstOrDefault();
            sReq.scar_Status = db2.scar_Status.Where(x => x.StatusID == req.StatusID).FirstOrDefault();


            //Attach to DBContext
            db2.scar_Requests.Attach(sReq);


            //Update Procedures
            foreach (Procedure p in AddProcedures)
            {
                scar_Procedures pro = sReq.scar_Procedures.Where(x => x.ProcedureID == p.Proc.ProcedureID && p.Proc.ProcedureID != 0).FirstOrDefault();
                if (pro != null)
                {
                    pro.EnRecovery = p.Proc.EnRecovery;
                    pro.IsPrimary = p.Proc.IsPrimary;
                    pro.Laterality = p.Proc.Laterality;
                    pro.OrthoFastTrack = p.Proc.OrthoFastTrack;
                    pro.ProcedureID = p.Proc.ProcedureID;
                    pro.ProcedureText = p.Proc.ProcedureText;
                    pro.RequestID = ReqID;
                    pro.Site = p.Proc.Site;
                }
                else
                {
                    pro = new scar_Procedures();
                    pro.EnRecovery = p.Proc.EnRecovery;
                    pro.IsPrimary = p.Proc.IsPrimary;
                    pro.Laterality = p.Proc.Laterality;
                    pro.OrthoFastTrack = p.Proc.OrthoFastTrack;
                    pro.ProcedureID = p.Proc.ProcedureID;
                    pro.ProcedureText = p.Proc.ProcedureText;
                    pro.RequestID = ReqID;
                    pro.Site = p.Proc.Site; ;

                    pro.scar_Requests = sReq;
                }

                //Update Surgeons
                pro.scar_Surgeons.Clear();
                foreach (scar_Surgeons s in p.Surgeons)
                {
                    pro.scar_Surgeons.Add(db2.scar_Surgeons.Where(x=> x.SurgeonID == s.SurgeonID).FirstOrDefault());
                }
            }


            //Set State and Save
            db2.Entry(sReq).State = System.Data.Entity.EntityState.Modified;
            db2.SaveChanges();
        }
    }