[英]DBContext - remove pending changes
我有一个 MVC 应用程序,每个请求创建一次 DBContext。
在此请求中,我尝试保存订单列表
...
foreach (var order in orders)
{
SaveOrder(order);
}
public SaveOrder(Order order)
{
_context.Orders.Add(order);
_context.SaveChanges();
}
...
但是,如果列表中的第一个订单引发异常,则其余订单都不会保存。
我试过捕捉异常然后使用
_context.Orders.Remove(order)
但是在下一次调用数据库上下文中的 SaveChanges() 时,原始异常仍然会触发。
一些文章似乎建议为每个动作使用一个新的上下文,并用 using 语句包装——但这并不昂贵(它不会每次都创建一个新的连接吗?)
这样做的正确方法是什么? 有没有办法删除所有挂起的更改?
谢谢
可能这会有所帮助
public void SaveOrders()
{
try
{
foreach (var order in orders)
{
if (!IsOrderEntryValid(order))
{
_invalidOrders.Add(order);
continue;
}
if(!_context.Orders.Exists(/* write your logic to check if the order exists*/))
_context.Orders.Add(order);
}
_context.SaveChanges();
}
catch(Exception ex)
{
// log the exception
}
}
public ValidateOrder(Order order)
{
// do some validations here that would not violate the data format and rules, cause violations and exceptions.
}
由于问题中给出的信息,这是非常通用的。 我敢肯定,您会想出验证和确保保存数据的方法不会因为数据库违规、约束违规、重复等而引发异常。您会从它抛出的异常中学到和/或必须记录它。 对我来说,一个不断发展的系统涉及对平台及其与数据相关的行为的学习。
要处理要从上下文中删除项目的情况,您需要将其与 DbContext 分离,而不是调用Remove
。 Remove
可能会导致一些不良后果,例如删除现有行。
因此,在您的情况下, SaveOrder 调用应该通过执行以下操作来工作:
public void SaveOrder(Order order)
{
try
{
_context.Orders.Add(order);
_context.SaveChanges();
}
catch (DbUpdateException ex)
{
_context.Entry(order).State = EntityState.Detached; // De-associate from the poisoned order.
// TODO: Consider logging that this order could not be saved or returning a result to that effect.
}
}
请注意,如果 Order 实体具有作为此操作的一部分添加/更新的子项,则您也需要分离它们。 IE
catch (DbUpdateException ex)
{
_context.Entry(order).State = EntityState.Detached;
foreach(var orderLine in order.OrderLines)
{
_context.Entry(orderLine).State = EntityState.Detached;
}
}
仅适用于由操作添加或以其他方式更新的行。 如果此操作未创建/更新客户记录,则您不希望分离 Order.Customer。
我更喜欢使用工作单元模式,它将插入新订单视为单个操作,包括一个工作单元。 如果我创建 5 个订单,每个订单彼此独立(1 个失败不会影响其他订单),那么它们是 5 个独立的操作。 启动作用域 DbContext 通常是避免交叉操作“中毒”的最安全选项,并且不会产生大量成本。 对于接触相同数据的操作,会产生额外的读取成本,尽管这些通常是按 ID 场景(客户按 ID、产品按 ID 等)获取的,因此它们的成本很低。 将订单周围的附加和分离状态弄得太多会导致更严重的问题,因为在 Save 调用之后,“订单”引用可能是,也可能不是现在被跟踪的实体。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.