C# 更新共享多对多关系的多个记录失败 细节
我有两个表(程序、外科医生)和一个查找表(ProcSurg),用于创建多对多关系C# 更新共享多对多关系的多个记录失败 细节,c#,entity-framework,dbcontext,C#,Entity Framework,Dbcontext,我有两个表(程序、外科医生)和一个查找表(ProcSurg),用于创建多对多关系 scar_Requests scar_Procedures scar_ProcSurg scar_Surgeons ------------- --------------- ------------- ------------- RequestID <> ProcedureID &
scar_Requests scar_Procedures scar_ProcSurg scar_Surgeons
------------- --------------- ------------- -------------
RequestID <> ProcedureID <> ProcedureID(fk) <> SurgeonID
... RequestID SurgeonID(fk) ...
...
我分离出保存记录这一部分的代码,试图找出我的问题
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>();
}
}
类过程
{
公共scar_过程过程{get;set;}
公共列表{get;set;}
公共无效删除urgeon(int SurgeonID)
{
外科医生.Remove(外科医生.Where(x=>x.SurgeonID==SurgeonID.FirstOrDefault());
}
公共程序()
{
外科医生=新列表();
}
}
保存代码:使用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();
}
}
private void SaveProcSurg()
{
使用(MCASURGContext db2=new MCASURGContext())
{
foreach(AddProcedures中的程序p)
{
if(p.Procedure.RequestID==0)
{
p、 Procedure.RequestID=ReqID;
}
p、 手术。疤痕外科医师。清除();
foreach(外科医师中的疤痕外科医师)
{
if(db2.ChangeTracker.Entries().Where(x=>x.Entity.SurgeonID==s.SurgeonID.FirstOrDefault()==null)
{
db2.scar_.Attach(s);
}
p、 程序。疤痕外科医师。添加(s);
}
如果(p.Procedure.ProcedureID==0)
{
scar_Procedures.Add(p.Procedures);
Entry(p.Procedure).State=System.Data.Entity.EntityState.Added;
}
其他的
{
db2.scar_Procedures.Attach(p.Procedures);
Entry(p.Procedure).State=System.Data.Entity.EntityState.Modified;
}
}
SaveChanges();
}
}
我尝试了几种不同的保存记录的方法,这是我最接近正确保存记录的方法
我觉得这与我将外科医生连接到实体然后连接到程序的方式有关。任何关于我在哪里可以找到答案的帮助、想法或建议都将非常好
我在google上搜索了一个多星期,我一直在想Entity Framework到底在做什么,但我对这一点还是很陌生
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() }); }
}
}
//内部变量
私人scar_请求请求;
私有列表AddProcedures=新列表();
//从数据库获取scar\u请求
私有void GetRequest()
{
使用(MCASURGContext db=new MCASURGContext())
{
req=db.scar_请求。包括(“scar_程序.scar_外科医生”)。包括(“scar_状态”)。包括(“scar_用户.scar_服务”)。其中(x=>x.RequestID==ReqID)。FirstOrDefault();
foreach(scar_Procedures.scar_Procedures中的scar_Procedures p){AddProcedures.Add(new Procedures(){Proc=p,surgeronics=p.scar_surgeronics.ToList()}
}
}
保持良好的状态,我会发布我的答案,因为我想我已经找到了答案。也许将来它会帮助别人
我完全重新编写了saving,删除了很多以前使用的无用代码,减少了对数据库的调用。还有其他我没有在上面发布的方法,它们保存了记录的其他部分,我将这些部分压缩为一个方法
基本上,我从数据库中获取记录及其联接表,并遍历所有需要更新的字段/联接表,然后将其保存回数据库。(现在看起来非常明显,但我以前尝试过这种方法,我一定是出了什么问题,因为在我尝试这种方法的前几次时,它不起作用。)
我不知道它是否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();
}
}
AddProcedures
集合中的对象(和/或其子对象)可能附加到另一个上下文。您从哪里获得AddProcedures
?您是在另一个尚未处理的上下文中从数据库加载它的吗?使用上面的(MCASURGContext DB=new MCASURGContext()){foreach(scar_Procedures p in req.scar_Procedures){AddProcedures.Add(new Procedures(){Procedures Procedures=p.scar_Procedures.ToList()}}是如何从数据库获取数据的。对DB的每个调用都被包装在一个Using(dbcontext)块中。我看不出您在Using块中使用了DB
。有一个变量名为req
。请您使用问题下方的“编辑”链接将这些详细信息直接添加到您的问题中。此处的注释中很难阅读代码片段。抱歉,上面更新了详细信息。谢谢你花时间看我的问题。
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();
}
}