C# EF 6:当我将元素标记为已删除时,集合长度减少
我试图先熟悉EF6代码、WPF和C。我使用了两个与一对多关系相关的实体 «模拟»是父级 «echeance»是孩子C# EF 6:当我将元素标记为已删除时,集合长度减少,c#,wpf,entity-framework,C#,Wpf,Entity Framework,我试图先熟悉EF6代码、WPF和C。我使用了两个与一对多关系相关的实体 «模拟»是父级 «echeance»是孩子 public partial class simulation : INotifyPropertyChanged { public long SimulationId { get; set; } ... ... ... public virtual ICollection<Echeance>
public partial class simulation : INotifyPropertyChanged
{
public long SimulationId { get; set; }
...
...
...
public virtual ICollection<Echeance> echeancier { get; set; }
public List<Echeance> echeancierCopy { get; set; }
...
...
...
}
public partial class Echeance : INotifyPropertyChanged
{
public long EcheanceId { get; set; }
public long SimulationId { get; set; }
public virtual simulation simulation { get; set; }
...
...
...
}
实际上,当我想修改«simulation»时,首先我从数据库中读取它,然后将«echeancier»集合克隆到«echeanceCopy»列表中,然后将«echeanceCopy»数据绑定到WPF数据网格中,这样我就可以在数据网格单元中以交互方式进行更改。当我要保存模拟时:
有两种情况:
1新模拟:我将«echeanceCopy»Lits转换为«echeancier»集合并保存。它很好用
2旧模拟:我将«echeanceCopy»Lits转换为«echeancier»集合并保存它。
如果«echeanceCopy»的长度小于«echeancier»,则我必须将«echeancier»中的元素标记为已删除元素,而不是«echeanceCopy»中的元素。当我这样做时,«echeancier»集合的长度会自动减少,这是一个问题,我一步一步地使用调试器,我不明白为什么
这里是集合和列表之间的转移代码
private void TransfertToOriginal(simulation item)
{
item.echeancierCopy.OrderBy(e => e.EchNumber);
item.echeancier.OrderBy(e => e.EchNumber);
int copylen = item.echeancierCopy.Count();
int origlen = item.echeancier.Count();
try
{
if (copylen > origlen)
for (int ii = 0; ii <= copylen - 1; ii++)
{
if (ii < origlen) //Copy and mark as Modified
EcheanceCopy(item, ii);
else //Add the new echeance and mark it as added
if (ii >= origlen)
{
item.echeancier.Add(item.echeancierCopy[ii]);
base.GetCurrentUoW().RegisterNew<Echeance>(item.echeancier.ElementAt(ii));
}
else
{
if (copylen < origlen)
{
for (int ii = 0; ii < origlen; ii++)
{
if (ii < copylen)
{
EcheanceCopy(item, ii);
}
else //the echeance is deleted then mark it as deleted
{
//the following line will cause length of "echeancier" collection to decrease
//automatically each time in loop and fire an exception when ii become > length of
//"echeancier" ... exception says : index out of limit
base.GetCurrentUoW().RegisterDeleted<Echeance>(item.echeancier.ElementAt(ii));
}
}
}
}
catch (Exception ex)
{
_logger.LogException(ex);
throw ex;
}
}
//Method for copy echeanceCopy-> echeancier
private void EcheanceCopy(simulation item, int index)
{
item.echeancier.ElementAt(index).DateEcheance = item.echeancierCopy[index].DateEcheance;
item.echeancier.ElementAt(index).MontantPrincipal = item.echeancierCopy[index].MontantPrincipal;
item.echeancier.ElementAt(index).MontantInteret = item.echeancierCopy[index].MontantInteret;
item.echeancier.ElementAt(index).MontantTTC = item.echeancierCopy[index].MontantTTC;
item.echeancier.ElementAt(index).MontantHT = item.echeancierCopy[index].MontantHT;
item.echeancier.ElementAt(index).MontantTVA = item.echeancierCopy[index].MontantTVA;
base.GetCurrentUoW().RegisterChanged<Echeance>(item.echeancier.ElementAt(index));
}
对不起,我忘了单位代码
//Mark entity as deleted
public void RegisterDeleted<T>(T item) where T : class
{
base.Entry<T>(item).State = EntityState.Deleted;
}
//Mark entity as Modified
public void RegisterChanged<T>(T item) where T : class
{
base.Entry<T>(item).State = EntityState.Modified;
}
//Mark entity as Added
public void RegisterNew<T>(T item) where T : class
{
base.Entry<T>(item).State = EntityState.Added;
}
下面是保存在数据库中的代码
public override void Modify(simulation item)
{
//If we are in Edit mode
try
{
if (item.SimulationId != 0)
{
//Detach the working collection from dbcontext
DetachEcheancier(item.echeancierCopy.ToList());
//Transfert the working collection to original collection
TransfertToOriginal(item);
}
else //New Simulation
{
//Copy all working collection elements to original collection
item.echeancier = new List<Echeance>(item.echeancierCopy);
//Mark all elements of original collection as added
SetEcheancierAsAdded(item);
}
base.Modify(item); //Then save (call SaveChanges() from uow
}
catch (Exception ex)
{
_logger.LogException(ex);
throw ex;
}
}
最后我找到了解决办法。实际上我创建了三个集合,一个用于删除元素,一个用于添加,一个用于修改
private void TransfertToOriginal(simulation item)
{
try
{
//Echeances that will be marked as deleted => found in "echeancier"
//and not in echeancierCopy
var EcheancesForDelete = item.echeancier.Except(item.echeancierCopy, new EcheanceNumberComparer());
//Echeances that will be marked as modified => found in 2 collections
var EcheancesForModify = item.echeancier.Intersect(item.echeancierCopy, new EcheanceNumberComparer());
//Echeances that will be marked as Added => found in "echeancierCopy" and not in "echeancier"
var EcheancesForAdd = item.echeancierCopy.Except(item.echeancier, new EcheanceNumberComparer());
//Beware to cast EcheancesForDelete collection To List otherwise an exception Collection was modified
foreach (Echeance ee in EcheancesForDelete.ToList())
{
base.GetCurrentUoW().Attach<Echeance>(ee);
base.GetCurrentUoW().RegisterDeleted<Echeance>(ee);
}
//Modification ....Don't forget ToList()
foreach (Echeance ee in EcheancesForModify.ToList())
{
base.GetCurrentUoW().Attach<Echeance>(ee);
base.GetCurrentUoW().RegisterChanged<Echeance>(ee);
}
//New records here
foreach (Echeance ee in EcheancesForAdd.ToList())
{
base.GetCurrentUoW().Attach<Echeance>(ee);
base.GetCurrentUoW().RegisterNew<Echeance>(ee);
}
}
catch (Exception ex)
{
_logger.LogException(ex);
throw ex;
}
}
比较器如下所示:
public class EcheanceNumberComparer : IEqualityComparer<Echeance>
{
public bool Equals(Echeance x, Echeance y)
{
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x.EchNumber == y.EchNumber;
}
public int GetHashCode(Echeance e)
{
if (Object.ReferenceEquals(e, null)) return 0;
int hashEcheanceNumber = e.EchNumber.GetHashCode();
return hashEcheanceNumber;
}
}
再见。如果删除某个元素或将其标记为已删除,则该元素将从集合中删除。如果已删除,是吗?。但你为什么要这么做?如果不想保存,请不要调用SaveChanges DbContext已是UnitOfWork。我想保存更改,所以我使用TransferToOriginal方法准备eCeancier集合以将其保存到数据库中。实际上,我后来也使用了SaveChanges,但我在代码中没有提到它。关于你的问题,我为什么要这样做?否则,我如何保存更改?您说如果我将集合的某个元素标记为已删除,它将从此集合中删除。这种行为正常吗?如果是,我不明白EF如何知道它必须从数据库中删除的记录(如果它们已经从原始集合中删除)?EF将为您处理所有必要的事情-您不必包装添加、更改和删除。EF有一个ChangeTracker,它会看到,如果你做了什么。谢谢你抱怨85,看来我有很多工作要做