我需要确认我的方法,我正在使用EF和ASP.NET MVC,我试图根据用户选择删除实体(即基于他们检查/取消选中的内容)。
要做到这一点,我正在查看从复选框中的表单传递的ID,匹配我在数据库中的内容,然后首先添加任何新的,然后删除任何不匹配的。
以下是我最初的代码:
[HttpPost]
public ActionResult Edit(int id, FormCollection collection, VMinstanceRole vmodel)
{
try
{
var instancerole = db.instanceRoles.Find(id);
if (ModelState.IsValid)
{
UpdateModel<instanceRole>(instancerole, "instanceRole");
var keys = instancerole.rights.Select( c => c.Id);
foreach (var pid in vmodel.selectedId.Except(keys))
{
var right = new right { Id = pid };
db.rights.Attach(right);
instancerole.rights.Add(right);
}
foreach (var pid in keys.Except(vmodel.selectedId))
{
var right = instancerole.rights.Where(c => c.Id == pid).Single();
instancerole.rights.Remove(right);
}
db.SaveChanges();
}
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch (InvalidCastException e)
{
return View();
}
}
但是,出现以下错误“集合已被修改;枚举操作可能无法执行”。
因此,为了尝试解决此问题,我决定保留一个单独的列表,然后根据列表删除它以克服错误:
[HttpPost]
public ActionResult Edit(int id, FormCollection collection, VMinstanceRole vmodel)
{
try
{
var instancerole = db.instanceRoles.Find(id);
List<right> removeList = new List<right>();
if (ModelState.IsValid)
{
UpdateModel<instanceRole>(instancerole, "instanceRole");
var keys = instancerole.rights.Select( c => c.Id);
foreach (var pid in vmodel.selectedId.Except(keys))
{
var right = new right { Id = pid };
db.rights.Attach(right);
instancerole.rights.Add(right);
}
foreach (var pid in keys.Except(vmodel.selectedId))
{
var right = instancerole.rights.Where(c => c.Id == pid).Single();
removeList.Add(right);
}
foreach (var right in removeList)
{
instancerole.rights.Remove(right);
}
db.SaveChanges();
}
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch (InvalidCastException e)
{
return View();
}
}
这似乎有效,但是,我不确定我是否做了正确的事情。主要是因为我正在做另一个循环。有没有更好的方法来解决这个问题还是足够好?
答案 0 :(得分:4)
您找到了一个标准解决方案。另一个有效的解决方案是在生成密钥对象的LINQ操作上调用ToList:这样做断开密钥与instanceroles集合,允许对原始集合进行任意独立修改。
答案 1 :(得分:0)
在使用foreach
进行枚举时无法编辑集合的原因已足够详细记录(仅检查“相关”链接到侧面),并且知道您不能这样做,您可以使用简单的for
循环并在删除项目时修改索引 - 这样可以保持一个循环。
for (int i = 0; i < max; i++) {
//if removing an item
//manipulate the index as desired...
i--;
}
答案 2 :(得分:0)
试试这个:
foreach (var pid in keys.Except(vmodel.selectedId).ToList())
{
var right = instancerole.rights.Where(c => c.Id == pid).Single();
instancerole.rights.Remove(right);
}
在删除第一个项目时,您在foreach循环中枚举的枚举器将被处理掉。