在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);
时,错误消息为
收藏被修改;枚举操作可能无法执行。
如果我执行此行CurrentAddress.Contacts.ToList().ForEach(r => db.Contacts.Remove(CurrentContacts));
而不是此行existingAddress.Contacts.Remove(CurrentContacts);
,那么我将收到错误消息
附加信息:未将对象引用设置为对象的实例。
我是EF的新手,所以我无法弄清楚如何从子表中删除数据。
我的实体关系是客户>地址>联系人
客户可能有多个地址,每个地址可能有多个联系方式。
我的完整代码如下,我用来更新父客户对象并尝试从地址和联系子表中删除特定数据,并在子表中插入两个新数据。
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();
}
答案 0 :(得分:2)
您的问题与EF没有直接关系,而是与Enumerables有关。
您无法调用Remove
,Add
或其他任何修改您当前枚举的集合的集合的内容。 (这就是为什么错误消息显示“集合已被修改;枚举操作可能无法执行。”)
这部分例如:
foreach (var CustContacts in existingAddress.Contacts.Where(a => a.ContactID == 5))
{
CurrentContacts = CustContacts;
existingAddress.Contacts.Remove(CurrentContacts);
}
您正在枚举联系人,并且在循环内删除联系人。一个简单的解决方法是调用ToList
(正如您在外部循环中所做的那样)以确保使用不同的枚举。
e.g。
foreach (var CustContacts in existingAddress.Contacts.Where(a => a.ContactID == 5).ToList())
{
CurrentContacts = CustContacts;
existingAddress.Contacts.Remove(CurrentContacts);
}
我不完全确定你想要实现的目标但是从你看来你可能会更好,如果你在数据库中有一个干净的级联删除实现(删除相关/连接)条目自动)。