这里有一个奇怪的。我在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
编辑2:这是我使用“分离”的最接近的工作解决方案。有趣的是,“分离”实际上需要大约2秒!不确定它在做什么,但它确实有效。
db.ExecuteStoreCommand("DELETE FROM ORDERITEM WHERE ID ={0}", orderitem.Id);
db.detach(orderitem);
重新查询和重新填充数据集会更快。我如何强制重新查询?我认为以下会这样做:
var order = db.order.First(r => r.Id == order.id);
编辑3:这似乎有助于强制刷新后删除,但仍然需要大约2秒:
db.Refresh(RefreshMode.StoreWins,Order.OrderItem);
我仍然没有真正理解为什么一个人不能仅仅重新查询Order.First(r => r.id == id)类型的查询信息需要花费不到2秒的时间。
这可能是因为当您执行ExecuteStoredCommand时,Order及其订单项已为上下文所知。 EF不知道该命令与Order的任何缓存副本有关,因此该命令将被发送到数据库,但不会更新任何已加载的实体状态。 WHere-因为第一个会查找任何加载的OrderItem,当被告知从DbSet中删除它时,它会查找引用该订单项的任何加载实体。
如果您不想确保在删除之前加载实体,那么您将需要检查是否已加载实体,并刷新或分离其关联的引用。
如果orderitem代表一个实体应该只能使用:
db.OrderItems.Remove(orderitem);
如果订单已加载,则应自动删除订单商品。如果订单未加载,没有丢失,将在稍后请求时从数据库加载,并从DB加载订单项集。
但是,如果要使用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();
}
}
这种方法的关键点。