我很难确定处理此问题的最佳方法......使用Entity Framework(和L2S),LINQ查询将返回IQueryable。我已经阅读了关于DAL / BLL是否应该返回IQueryable,IEnumerable或IList的各种意见。假设我们使用IList,那么查询会立即运行,并且该控件不会传递到下一层。这使得单元测试等更容易。您无法在更高级别优化查询,但您可以简单地创建另一种方法,允许您优化查询并仍然返回IList。还有更多的利弊。到目前为止一切都很好。
现在实体框架和延迟加载。我在.NET 4 / VS 2010中使用POCO对象和代理。在表示层我做:
foreach (Order order in bll.GetOrders())
{
foreach (OrderLine orderLine in order.OrderLines)
{
// Do something
}
}
在这种情况下,GetOrders()返回IList,因此它会在返回PL之前立即执行。但是在下一个foreach中,你有延迟加载,它在获取所有OrderLines时执行多个SQL查询。所以基本上,PL在错误的层中“按需”运行SQL查询。
有没有明智的方法可以避免这种情况?我可以关闭延迟装载,但是有什么能让这个“功能”让每个人都抱怨EF1没有?而且我承认它在很多场景中非常有用。所以我看到了几个选项:
还有其他选择或建议吗?我还没有找到一个真正让我信服的选择。
答案 0 :(得分:0)
您可以让您的方法接受某种加载策略。
Func<ObjectSet<Order>, ObjectQuery<Order>> loadSpan =
orders=> orders.Include("OrderLines");
foreach (Order order in bll.GetOrders(loadSpan))
{
foreach (OrderLine orderLine in order.OrderLines)
{
// Do something
}
}
在您的GetOrders方法中,您可以执行类似
的操作public IList<Oorder> GetOrders(
Func<ObjectSet<Order>, ObjectQuery<Order>> loadSpan)
{
var ordersWithSpan = loadSpan(context.OrderSet);
var orders = from order in ordersWithSpan
where ...your normal filters etc
return orders.ToList();
}
这将允许您为每个用例指定整个加载图。 您可以在某些包装类中包含这些策略,以便编写:
//wrapped in a static class "OrderLoadSpans"
foreach (Order order in bll.GetOrders(OrderLoadSpans.WithOrderLines))
HTH