这里有一个奇怪的人。我在SQL Server 2012和C#上使用EF 6。
如果我使用DeleteObject删除记录,则会得到:
//order.orderitem count = 11
db.OrderItem.DeleteObject(orderitem);
db.SaveChanges();
var order = db.order.First(r => r.Id == order.id);
//Order.OrderItem count = 10, CORRECT
如果我使用ExecuteStoreCmd内联DML删除订单项,则会得到:
//order.orderitem count = 11
db.ExecuteStoreCommand("DELETE FROM ORDERITEM WHERE ID ={0}", orderitem.Id);
var order = db.Order.First(r => r.Id == order.id);
//order.orderitem count = 11, INCORRECT, should be 10
因此ExecuteStoreCommand版本报告11,但是肯定从数据库中删除了OrderItem,因此它应该报告10。另外,我还以为First()会进行Eager搜索,从而重新填充了“ order.orderitem”集合。 >
有什么想法为什么会这样?谢谢。
编辑:我正在使用ObjectContext
EDIT2:这是我使用“分离”时最接近的工作解决方案。有趣的是,“分离”实际上需要大约2秒钟!不知道它在做什么,但是它可以工作。
db.ExecuteStoreCommand("DELETE FROM ORDERITEM WHERE ID ={0}", orderitem.Id);
db.detach(orderitem);
重新查询和重新填充数据集会更快。如何强制重新查询?我认为以下可以做到:
var order = db.order.First(r => r.Id == order.id);
EDIT3:这似乎可以强制刷新后删除,但仍然需要大约2秒钟:
db.Refresh(RefreshMode.StoreWins,Order.OrderItem);
我仍然不是很明白为什么不能只作为Order重新查询。First(r => r.id == id)类型查询通常花费不到2秒的时间。
答案 0 :(得分:1)
这可能是因为执行ExecuteStoredCommand时上下文已经知道Order及其订单项。 EF不知道该命令与Order的任何缓存副本有关,因此该命令将发送到数据库,但不会更新任何已加载的实体状态。在这里,因为第一个将查找任何已加载的OrderItem,并在被告知将其从DbSet中删除时,它将查找任何引用该订单项的已加载实体。
如果您不想在删除之前确保已加载实体,则需要检查是否已加载实体,并刷新或分离其关联的引用。
如果订单项代表一个实体,则应该可以使用:
db.OrderItems.Remove(orderitem);
如果已加载订单,则订单项应自动删除。如果未加载订单,则不会丢失,稍后会在请求时从数据库加载订单,并从数据库加载订单项集。
但是,如果要使用SQL执行方法,则分离任何本地实例都应将其从本地缓存中删除。
db.ExecuteStoreCommand("DELETE FROM ORDERITEM WHERE ID ={0}", orderitem.Id);
var existingOrderItem = db.OrderItems.Local.SingleOrDefault(x => x.Id == orderItem.Id);
if(existingOrderItem != null)
db.Entity(existingOrderItem).State = EntityState.Detached;
我不认为您需要检查orderItem的“订单”以刷新除此以外的任何内容,但是我不确定100%是否对此表示满意。通常,尽管要修改数据状态,但我还是选择加载适用的顶级实体并删除其子代。
因此,如果我有命令从订单中删除订单商品:
public void RemoveOrderItem(int orderId, int orderItemId)
{
using (var context = new MyDbContext())
{
// TODO: Validate that the current user session has access to this order ID
var order = context.Orders.Include(x => x.OrderItems).Single(x => x.OrderId == orderId);
var orderItem = order.OrderItems.SingleOrDefault(x => x.OrderItemId == orderItemId);
if (orderItem != null)
order.OrderItems.Remove(orderItem);
context.SaveChanges();
}
}
这种方法的关键点。