我有一个父实体(治疗),其中包含一组子实体(细分)。我有一个save方法接受处理,确定它是新的还是现有的,然后将它添加到objectContext或根据它是新的还是现有的方法将它附加到对象上下文。
它与主要实体中的孩子做同样的事情。它迭代子实体的集合,然后根据需要添加或更新。
我试图让它做的是删除任何丢失的子对象。问题是,当我更新父对象然后将其附加到对象上下文时,父对象则具有来自DB的子对象的集合。不是我最初传入的集合。所以如果我有一个3段的治疗,我从集合中删除一个段,然后将治疗传递给我的保存方法,一旦将治疗对象附加到objectcontext,它拥有的段数从2变为3。
我做错了什么?
以下是我的保存方法的代码:
public bool Save(Treatment myTreatment, modelEntities myObjectContext)
{
bool result = false;
if (myObjectContext != null)
{
if (myTreatment.Treatment_ID == 0)
{
myObjectContext.Treatments.AddObject(myTreatment);
}
else
{
if (myTreatment.EntityState == System.Data.EntityState.Detached)
{
myObjectContext.Treatments.Attach(myTreatment);
}
myObjectContext.ObjectStateManager.ChangeObjectState(myTreatment, System.Data.EntityState.Modified);
myObjectContext.Treatments.ApplyCurrentValues(myTreatment);
}
foreach (Segment mySegment in myTreatment.Segments)
{
if (mySegment.SegmentID == 0)
{
myObjectContext.ObjectStateManager.ChangeObjectState(mySegment, System.Data.EntityState.Added);
myObjectContext.Segments.AddObject(mySegment);
}
else
{
if (mySegment.EntityState == System.Data.EntityState.Detached)
{
myObjectContext.Segments.Attach(mySegment);
}
myObjectContext.ObjectStateManager.ChangeObjectState(mySegment, System.Data.EntityState.Modified);
myObjectContext.Segments.ApplyCurrentValues(mySegment);
}
}
}
result = (myObjectContext.SaveChanges(SaveOptions.None) != 0);
return result;
}
的 的 *编辑* * ** 基于下面的一些反馈,我修改了“保存”方法。新方法实现如下。但是,它仍然不会删除已从myTreatments.Segments集合中删除的细分。
public bool Save(Treatment myTreatment, tamcEntities myObjectContext)
{
bool result = false;
if (myObjectContext != null)
{
if (myTreatment.Treatment_ID == 0)
{
myObjectContext.Treatments.AddObject(myTreatment);
}
else
{
if (myTreatment.EntityState == System.Data.EntityState.Detached)
{
myObjectContext.Treatments.Attach(myTreatment);
}
myObjectContext.ObjectStateManager.ChangeObjectState(myTreatment, System.Data.EntityState.Modified);
}
foreach (Segment mySegment in myTreatment.Segments)
{
if (mySegment.SegmentID == 0)
{
myObjectContext.ObjectStateManager.ChangeObjectState(mySegment, System.Data.EntityState.Added);
}
else
{
myObjectContext.ObjectStateManager.ChangeObjectState(mySegment, System.Data.EntityState.Modified);
}
}
}
result = (myObjectContext.SaveChanges(SaveOptions.None) != 0);
return result;
}
最终编辑 我终于得到了它的工作。这是更新的Save方法,它正常工作。我必须在局部变量中保存Segments的初始列表,然后在将其附加到数据库后将其与myTreatments.Segments列表进行比较,以确定要删除的Segments列表,然后迭代该列表并删除匹配来自新附加的myTreatment.Segments列表的细分。我还根据以下几个响应者的建议删除了objectcontext的传入。
public bool Save(Treatment myTreatment)
{
bool result = false;
List<Segment> myTreatmentSegments = myTreatment.Segments.ToList<Segment>();
using (tamcEntities myObjectContext = new tamcEntities())
{
if (myTreatment.Treatment_ID == 0)
{
myObjectContext.Treatments.AddObject(myTreatment);
}
else
{
if (myTreatment.EntityState == System.Data.EntityState.Detached)
{
myObjectContext.Treatments.Attach(myTreatment);
}
myObjectContext.ObjectStateManager.ChangeObjectState(myTreatment, System.Data.EntityState.Modified);
}
// Iterate over all the segments in myTreatment.Segments and update their EntityState to force
// them to update in the DB.
foreach (Segment mySegment in myTreatment.Segments)
{
if (mySegment.SegmentID == 0)
{
myObjectContext.ObjectStateManager.ChangeObjectState(mySegment, System.Data.EntityState.Added);
}
else
{
myObjectContext.ObjectStateManager.ChangeObjectState(mySegment, System.Data.EntityState.Modified);
}
}
// Create list of "Deleted" segments
List<Segment> myDeletedSegments = new List<Segment>();
foreach (Segment mySegment in myTreatment.Segments)
{
if (!myTreatmentSegments.Contains(mySegment))
{
myDeletedSegments.Add(mySegment);
}
}
// Iterate over list of "Deleted" segments and delete the matching segment from myTreatment.Segments
foreach (Segment mySegment in myDeletedSegments)
{
myObjectContext.ObjectStateManager.ChangeObjectState(mySegment, System.Data.EntityState.Deleted);
}
result = (myObjectContext.SaveChanges(SaveOptions.None) != 0);
}
return result;
}
答案 0 :(得分:1)
好的,再试一次。
当您说“删除”时,您的意思是标记为已删除。
您正在调用ChangeObjectState以将状态更改为已修改。
所以如果你发送3,一个删除,一个修改,一个不变;然后在调用保存更改之前,所有内容都会被标记为已修改。
答案 1 :(得分:1)
也许我错过了一些东西,但对我来说这段代码看起来过于繁琐。 如果我在这里错误的轨道并误解了你,请耐心等待我。
关于应删除的对象,我建议您将这些对象存储在仅包含已删除项目的单独集合中。您可以从ObjectContext
删除它们。
我会调用myObjectContext.SaveChanges()
而不是调用ApplyCurrentValues。在这种情况下,ApplyCurrentValues的缺点是它不会处理与您正在保存的实体有关系的任何其他实体。
将标量值从提供的对象复制到对象中 具有相同键的ObjectContext。
由于其他Segments
已经通过使用SaveChanges()附加到您的Treatment
,它们将自动添加到上下文中,或者如果已经添加,则会更新。
这应该使得对EntityStates的所有手动处理都不必要。
修改强> 现在我看到这是怎么回事......
在你的某个地方你编码 - 在这个Save()方法之外 - 你正在删除Segment实例。麻烦在于你的ObjectContext 完全没有意识到这个问题。怎么应该......?
您可能已销毁某个Segment实体的实例,但由于实体已分离,这意味着它们与ObjectContext的无连接。因此,上下文完全不知道你做了什么。
因此,当您附加处理时,上下文仍然认为所有段都存在,因为它不知道删除并将它们再次添加到处理,就像从未发生过一样。
<强>解决方案:强> 就像我上面已经说过的那样,你需要跟踪你删除的实体。
在那些删除细分的地方,不要删除它们,但是:
Remove()
。List<Segment>
。我们称之为deletedSegments。Save()
方法ObjectContect.Delete()
。此外,与Tomas Voracek提到的一样,最好使用更多本地的上下文。仅在save方法中创建它,而不是将其作为参数传递。