实体框架:无法删除子数据
本文关键字:删除 数据 框架 实体 | 更新日期: 2023-09-27 18:16:21
在foreach循环中控制迭代时抛出错误。
foreach (var existingAddress in existingCustomer.Addresses.Where(a => a.AddressID == 5).ToList())
{
foreach (var CustContacts in existingAddress.Contacts.Where(a => a.ContactID == 5))
{
CurrentContacts = CustContacts;
existingAddress.Contacts.Remove(CurrentContacts);
//CurrentAddress.Contacts.ToList().ForEach(r => db.Contacts.Remove(CurrentContacts));
}
CurrentAddress = existingAddress;
existingCustomer.Addresses.Remove(CurrentAddress);
//existingCustomer.Addresses.ToList().ForEach(r => db.Addresses.Remove(CurrentAddress));
}
当existingAddress.Contacts.Remove(CurrentContacts);
行执行时,错误信息为
Collection被修改;不能执行枚举操作。
如果我执行这行CurrentAddress.Contacts.ToList().ForEach(r => db.Contacts.Remove(CurrentContacts));
而不是这行existingAddress.Contacts.Remove(CurrentContacts);
,那么我得到的错误信息是
附加信息:对象引用未设置为对象的实例。
我是EF的新手,所以我不知道如何从子表中删除数据。
我的实体关系是Customer> Address> Contacts
客户可以有多个地址,每个地址可以有多个联系方式。
我的完整代码如下所示,我用来更新父客户对象,并试图从地址和联系人子表中删除特定数据,并在子表中插入两个新数据。
private void button3_Click(object sender, EventArgs e)
{
Addresses CurrentAddress = null;
Contacts CurrentContacts = null;
using (var db = new TestDBContext())
{
var existingCustomer = db.Customer
.Include(a => a.Addresses.Select(x => x.Contacts))
.FirstOrDefault(p => p.CustomerID == 5);
existingCustomer.FirstName = "Test Customer122";
// selecting address
foreach (var existingAddress in existingCustomer.Addresses.Where(a => a.AddressID == 5).ToList())
{
foreach (var CustContacts in existingAddress.Contacts.Where(a => a.ContactID == 5))
{
CurrentContacts = CustContacts;
existingAddress.Contacts.Remove(CurrentContacts);
//CurrentAddress.Contacts.ToList().ForEach(r => db.Contacts.Remove(CurrentContacts));
}
CurrentAddress = existingAddress;
existingCustomer.Addresses.Remove(CurrentAddress);
//existingCustomer.Addresses.ToList().ForEach(r => db.Addresses.Remove(CurrentAddress));
}
Addresses oAdrModel = new Addresses();
oAdrModel.Address1 = "test add2";
oAdrModel.Address2 = "test add2";
oAdrModel.SerialNo = 3;
oAdrModel.IsDefault = true;
oAdrModel.CustomerID = existingCustomer.CustomerID;
db.Addresses.Add(oAdrModel);
Contacts ContactModel = new Contacts();
ContactModel.Phone = "1111111-33";
ContactModel.Fax = "1-1111111";
ContactModel.SerialNo = 4;
ContactModel.IsDefault = true;
ContactModel.AddressID = CurrentAddress.AddressID;
db.Contacts.Add(ContactModel);
db.SaveChanges();
}
}
实体相关类
public class CustomerBase
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string Address1 { get; set; }
[NotMapped]
public string Address2 { get; set; }
[NotMapped]
public string Phone { get; set; }
[NotMapped]
public string Fax { get; set; }
}
public class Customer : CustomerBase
{
public virtual List<Addresses> Addresses { get; set; }
}
public class Addresses
{
[Key]
public int AddressID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public bool IsDefault { get; set; }
public int SerialNo { get; set; }
public virtual List<Contacts> Contacts { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; }
}
public class Contacts
{
[Key]
public int ContactID { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public bool IsDefault { get; set; }
public int SerialNo { get; set; }
public int AddressID { get; set; }
public virtual Addresses Customer { get; set; }
}
完整工作代码
using (var db = new TestDBContext())
{
//db.Database.Log = s => MyLogger.Log("EFApp", s);
var existingCustomer = db.Customer
.Include(a => a.Addresses.Select(x => x.Contacts))
.FirstOrDefault(p => p.CustomerID == 5);
existingCustomer.FirstName = "Test Customer123";
existingCustomer.Addresses.Where(a => a.AddressID == 5).ToList().ForEach(r => db.Addresses.Remove(r));
existingCustomer.Addresses.Where(a => a.AddressID == 5).SelectMany(ad => ad.Contacts).Where(c=> c.ContactID==5).ToList().ForEach(r => db.Contacts.Remove(r));
Addresses oAdrModel = new Addresses();
oAdrModel.Address1 = "test xxx";
oAdrModel.Address2 = "test xxx";
oAdrModel.SerialNo = 3;
oAdrModel.IsDefault = true;
oAdrModel.CustomerID = 5;
db.Addresses.Add(oAdrModel);
db.SaveChanges();
int CurAddressID = oAdrModel.AddressID;
Contacts ContactModel = new Contacts();
ContactModel.Phone = "XX-1111111-33";
ContactModel.Fax = "XX-1-1111111";
ContactModel.SerialNo = 4;
ContactModel.IsDefault = true;
ContactModel.AddressID = CurAddressID;
db.Contacts.Add(ContactModel);
db.SaveChanges();
}
您的问题与EF没有直接关系,而是与Enumerables有关。您不能在当前枚举的集合上调用Remove
、Add
或其他任何修改集合的方法。(这就是为什么错误消息显示"Collection was modified;不能执行枚举操作。")
这部分例如:
foreach (var CustContacts in existingAddress.Contacts.Where(a => a.ContactID == 5))
{
CurrentContacts = CustContacts;
existingAddress.Contacts.Remove(CurrentContacts);
}
您正在枚举联系人并在循环中删除联系人。一个简单的解决方法是调用ToList
(正如您在外部循环中所做的那样)以确保您正在使用不同的枚举。
。
foreach (var CustContacts in existingAddress.Contacts.Where(a => a.ContactID == 5).ToList())
{
CurrentContacts = CustContacts;
existingAddress.Contacts.Remove(CurrentContacts);
}
我不完全确定你想要实现什么,但从外观上看,如果你在数据库中有一个干净的级联删除(自动删除相关/连接的条目),你可能会更好。