使用MVC3 Entity Framework 4.3 Code First从集合中删除chlid对象
本文关键字:集合 删除 对象 chlid First Code Entity MVC3 Framework 使用 | 更新日期: 2023-09-27 18:28:51
我发现了许多与我的问题非常相似的帖子,但它们似乎都使用了DeleteObject()
方法,而在我使用的EF版本中似乎不存在这种方法!(尽管我很可能找错地方了)
不管怎样,我的问题。我有两个类,User
和Email
,其中用户可以拥有许多电子邮件。我有一个编辑表单,可以很高兴地编辑每个用户的所有电子邮件地址。我希望通过清除编辑表单中的文本框来删除每个电子邮件地址(稍后使用与每个框关联的删除按钮触发的JavaScript功能来完成)。为此,当数据返回时,我循环查看所有电子邮件地址,并测试地址属性是否为null,此时我想完全删除Email
对象。下面是我的编辑控制器,它(不)做业务:
[HttpPost]
public ActionResult Edit(int id, User User)
{
try
{
foreach (Email Email in User.Emails)
{
if (Email.Address == null)
{
User.Emails.Remove(Email);
}
else
{
db.Entry(Email).State = EntityState.Modified;
}
}
db.Entry(User).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return RedirectToAction("Index");
}
}
这在一定程度上起到了作用,使用调试器我可以看到它很高兴地从User
中删除Email
对象,但一旦它完成了这一操作,当它试图再次通过循环时就会抛出异常:
Message=Collection was modified; enumeration operation may not execute.
我的问题是:删除Email
对象的正确方法是什么,不仅从User
中删除,而且从我的数据库中删除?
提前感谢;-)
编辑:
我修改了我的控制器,创建了两个列表,一个用于带有和地址的Emails
,另一个用于地址为空的列表,并循环通过这些列表:
[HttpPost]
public ActionResult Edit(int id, User User)
{
try
{
var notNullEmails = User.Emails.Where(e => e.Address != null).ToList();
foreach (Email Email in notNullEmails)
{
db.Entry(Email).State = EntityState.Modified;
}
var isNullEmails = User.Emails.Where(e => e.Address == null).ToList();
foreach (Email Email in isNullEmails)
{
db.Emails.Remove(Email);
}
db.Entry(User).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return RedirectToAction("Index");
}
}
但这导致了这个例外:
Message=The object cannot be deleted because it was not found in the ObjectStateManager.
因此,我调整了用于空地址的foreach
,以明确地将要删除的电子邮件拉到上下文中,如下所示:
var isNullEmails = User.Emails.Where(e => e.Address == null).ToList();
foreach (Email Email in isNullEmails)
{
Email EmailToDelete = db.Emails.Find(Email.Id);
db.Emails.Remove(EmailToDelete);
}
但这导致了这个例外:
Message=Value cannot be null.
我想我能做到这一点要感谢你们,但我需要更多的帮助:-)
您有两个不同的问题:
一种是,在迭代集合时不能从集合中删除项。使用.ToList()遍历我制作的列表副本。
另一种是,调用您正在调用的Remove()方法只是删除与User的关系,而不是从数据库中实际删除它。如果数据库强制执行,这将生成引用完整性错误
相反,您希望对电子邮件数据库集调用Remove。
context.emails.Remove(email);
Remove()是DbContext使用的方法。DeleteObject和RemoveObject是较旧的/可供选择的API
我知道你说过不使用DeleteObject,但我也有同样的问题,我认为我应该在这里为其他搜索这个问题的人发布答案:
int i = User.Emails.Count - 1;
while (true)
{
if (i<0)
{
break;
}
Db.Emails.DeleteObject(User.Emails.ElementAt<Email>(i));
i--;
}
我知道这真的很旧,但我想我可能应该用我发现的实际有效的方法来回答它:
foreach(Email email in User.Emails)
{
if(string.IsNullOrEmpty(email.Address))
{
db.Entry(email).State = System.Data.EntityState.Deleted;
}
}
db.SaveChanges();
我认为这是迄今为止我见过的最简单的解决方案,但如果有更好的方法,请随时纠正我。