IQueryable 是否会在每次访问对象时重新查询数据库?
Does IQueryable re-query the database on every access of the object?
我的代码中有一个错误,最终设法将其追溯到我对 IQueryable 语句的使用,但是所发生的事情的含义给我留下了一些问题我希望有人对 Entity Framework 可以阐明一些问题,以便我可以改进。
(N.B。这段代码最初是在单个 foreach 循环中,但我在那里也遇到了一个错误,虽然我不确定它是否是同一个)
IQueryable<SystemOrder> Orders = _ctx.SystemOrder.Where(x => x.ordStatus == 1 && x.rctStatus == 0).OrderBy(x => x.Id);
Console.WriteLine(Orders.Count());
AddressLabel l;
foreach (SystemOrder Order in Orders)
{
Order.rctStatus = 1;
}
_ctx.SaveChanges();
foreach (SystemOrder Order in Orders)
{
l = new AddressLabel(Order);
SendOrderConfirmationEmail(Order, l);
Order.rctStatus = 2;
}
_ctx.SaveChanges();
foreach (SystemOrder Order in Orders)
{
l = new AddressLabel(Order);
CreateOrderFiles(Order, l);
Order.rctStatus = 3;
}
_ctx.SaveChanges();
foreach (SystemOrder Order in Orders)
{
SystemOrder result = PushToTill(Order);
Order.ordStatus = result.ordStatus;
}
_ctx.SaveChanges();
所以问题是结果只在第一个 foreach 循环中起作用,所有后续循环都被忽略,因为 "Orders" IQueryable 没有返回任何结果。我很困惑,直到我突然意识到它可能是 运行 每次访问订单时的查询,因为它不在内存中。将结果推送到列表并对其进行处理避免了这个问题。
如果是这种情况,我有几个问题:
- 我的假设是否真的正确,因为每个 foreach 都在重新查询数据库?
- 如果代码包含在单个 foreach 中,这不会发生吗?
- 在这种情况下,最好的方法是什么?使用内存或多个查询?
我需要单独的 foreach 循环的原因是我可以在每次状态更新时调用 SaveChanges(),因为您不能在循环内调用它。效率低下,但我不确定在这种情况下最好的方法。
谢谢:)
1 - 是
2 - 是的,单个 foreach 应该可以工作
3 - 不清楚是什么情况,我觉得使用single foreach是一个很好的解决方案
In situations like this, what would be the best approach? Using memory
or multiple queries?
使用任何一种方法产生最易读的代码。如果有多个 foreach 循环使您的代码更具可读性,请替换
IQueryable<SystemOrder> Orders = _ctx.SystemOrder
.Where(x => x.ordStatus == 1 && x.rctStatus == 0)
.OrderBy(x => x.Id);
与:
List<SystemOrder> Orders = _ctx.SystemOrder
.Where(x => x.ordStatus == 1 && x.rctStatus == 0)
.OrderBy(x => x.Id)
.ToList();
调用 ToList()
访问数据库(即运行一次查询)。枚举 List<T>
不会访问数据库。与许多人的直觉相反,具体化查询不会中断 _ctx.SaveChanges()
。在更改跟踪的上下文中,通过 ToList()
实现查询与通过 foreach
.
实现查询没有特别不同
我的代码中有一个错误,最终设法将其追溯到我对 IQueryable 语句的使用,但是所发生的事情的含义给我留下了一些问题我希望有人对 Entity Framework 可以阐明一些问题,以便我可以改进。
(N.B。这段代码最初是在单个 foreach 循环中,但我在那里也遇到了一个错误,虽然我不确定它是否是同一个)
IQueryable<SystemOrder> Orders = _ctx.SystemOrder.Where(x => x.ordStatus == 1 && x.rctStatus == 0).OrderBy(x => x.Id);
Console.WriteLine(Orders.Count());
AddressLabel l;
foreach (SystemOrder Order in Orders)
{
Order.rctStatus = 1;
}
_ctx.SaveChanges();
foreach (SystemOrder Order in Orders)
{
l = new AddressLabel(Order);
SendOrderConfirmationEmail(Order, l);
Order.rctStatus = 2;
}
_ctx.SaveChanges();
foreach (SystemOrder Order in Orders)
{
l = new AddressLabel(Order);
CreateOrderFiles(Order, l);
Order.rctStatus = 3;
}
_ctx.SaveChanges();
foreach (SystemOrder Order in Orders)
{
SystemOrder result = PushToTill(Order);
Order.ordStatus = result.ordStatus;
}
_ctx.SaveChanges();
所以问题是结果只在第一个 foreach 循环中起作用,所有后续循环都被忽略,因为 "Orders" IQueryable 没有返回任何结果。我很困惑,直到我突然意识到它可能是 运行 每次访问订单时的查询,因为它不在内存中。将结果推送到列表并对其进行处理避免了这个问题。
如果是这种情况,我有几个问题:
- 我的假设是否真的正确,因为每个 foreach 都在重新查询数据库?
- 如果代码包含在单个 foreach 中,这不会发生吗?
- 在这种情况下,最好的方法是什么?使用内存或多个查询?
我需要单独的 foreach 循环的原因是我可以在每次状态更新时调用 SaveChanges(),因为您不能在循环内调用它。效率低下,但我不确定在这种情况下最好的方法。
谢谢:)
1 - 是
2 - 是的,单个 foreach 应该可以工作
3 - 不清楚是什么情况,我觉得使用single foreach是一个很好的解决方案
In situations like this, what would be the best approach? Using memory or multiple queries?
使用任何一种方法产生最易读的代码。如果有多个 foreach 循环使您的代码更具可读性,请替换
IQueryable<SystemOrder> Orders = _ctx.SystemOrder
.Where(x => x.ordStatus == 1 && x.rctStatus == 0)
.OrderBy(x => x.Id);
与:
List<SystemOrder> Orders = _ctx.SystemOrder
.Where(x => x.ordStatus == 1 && x.rctStatus == 0)
.OrderBy(x => x.Id)
.ToList();
调用 ToList()
访问数据库(即运行一次查询)。枚举 List<T>
不会访问数据库。与许多人的直觉相反,具体化查询不会中断 _ctx.SaveChanges()
。在更改跟踪的上下文中,通过 ToList()
实现查询与通过 foreach
.