Mic*_*mig 5 asp.net-mvc entity-framework disconnected
我看一下类似问题的一些答案,但它们似乎并不适合我的.
我正在尝试合并来自实体框架的模式:DbContext(第90页),它似乎不起作用.我正在使用的代码如下:
[HttpPost]
public ActionResult Edit(Order order)
{
if (ModelState.IsValid)
{
db.Orders.Add(order);
db.Entry(order).State = EntityState.Modified;
foreach (var orderDetail in order.OrderDetails)
{
if (orderDetail.OrderId == 0)
{
db.Entry(orderDetail).State = EntityState.Added;
}
else
{
db.Entry(orderDetail).State = EntityState.Modified;
}
// The example order that I'm updating has two child entities
// so this orderId will be for the third, added one.
int addedOrderDetailId = order.OrderDetails[2].OrderId;
}
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CustomerId = new SelectList(db.Customers, "CustomerId", "CompanyName", order.CustomerId);
return View(order);
}
Run Code Online (Sandbox Code Playgroud)
我一直在运行一个示例,其中Order对象有两个现有的OrderDetail对象,我正在尝试添加第三个.我包含了addedOrderDetailId变量,因此我可以将它添加到'Watch'并查看它何时更改
我发现正在发生的是添加的OrderDetail对象的OrderId(当输入foreach循环时为0)正由实体框架更新到Order对象的OrderId.这发生在第一次迭代到foreach循环之后(当第一个子实体的状态更改为修改时.这意味着所有三个子节点都被标记为已修改.这导致SaveChanges()尝试更新条目进入不存在的数据库.
如果有其他人遇到过这个问题,那么我会很乐意为你解决这个问题.我还必须处理被删除的现有子对象,但我还没有解决这个问题,所以如果有人知道这种模式,那也值得赞赏.
编辑:
在获取Slauma的建议并删除db.Orders.Add(order)之后.我能够将调用移动到foreach循环下面的db.Entry(order).State.这允许我遍历循环并将每个OrderDetail对象的状态设置为针对现有对象进行修改并添加为添加的对象.然后,我只需将父级的OrderId分配给子级的OrderId,并且更新成功.我还包括了我在编辑过程中用来删除子对象的代码.我不确定这是多么有效,但它确实有效.这是修改后的代码:
[HttpPost]
public ActionResult Edit(Order order)
{
if (ModelState.IsValid)
{
List<int> previousProductIds = db.OrderDetails
.Where(ep => ep.OrderId == order.OrderId)
.Select(ep => ep.ProductId)
.ToList();
List<int> currentProductIds = order.OrderDetails
.Select(o => o.ProductId)
.ToList();
List<int> deletedProductIds = previousProductIds
.Except(currentProductIds).ToList();
foreach (var deletedProductId in deletedProductIds)
{
OrderDetail deletedOrderDetail = db.OrderDetails
.Where(od => od.OrderId == order.OrderId && od.ProductId == deletedProductId)
.Single();
db.Entry(deletedOrderDetail).State = EntityState.Deleted;
}
foreach (var orderDetail in order.OrderDetails)
{
if (orderDetail.OrderId == 0)
{
db.Entry(orderDetail).State = EntityState.Added;
orderDetail.OrderId = order.OrderId;
}
else
{
db.Entry(orderDetail).State = EntityState.Modified;
}
}
db.Entry(order).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CustomerId = new SelectList(db.Customers, "CustomerId", "CompanyName", order.CustomerId);
return View(order);
}
Run Code Online (Sandbox Code Playgroud)
从代码中删除这一行:
db.Orders.Add(order);
Run Code Online (Sandbox Code Playgroud)
这实际上会将包含所有 orderDetails 的订单放入状态Added。关系修复(在中自动发生Add)会将 all 设置OrderId为订单的键。当您进入循环时,适用于所有详细信息项,并且您始终进入将状态设置为 的分支。当循环完成时,orderDetail 项目不再处于状态。 OrderDetailsorderDetail.OrderId!= 0ModifiedAdded