【问题标题】:IQueryable and lazy loadingIQueryable 和延迟加载
【发布时间】:2011-02-16 20:09:42
【问题描述】:

我很难确定处理此问题的最佳方法...使用实体框架(和 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 中,您有延迟加载,它在获取所有 OrderLine 时执行多个 SQL 查询。所以基本上,PL 在错误的层“按需”运行 SQL 查询。

有什么明智的方法可以避免这种情况吗?我可以关闭延迟加载,但是拥有这个每个人都在抱怨 EF1 没有的“功能”又有什么意义呢?而且我承认它在许多情况下都非常有用。所以我看到了几个选项:

  1. 以某种方式删除实体中的所有关联并添加方法以返回它们。这违背了默认的 EF 行为/代码生成,并且使得执行一些复合(多实体)LINQ 查询变得更加困难。这似乎是倒退了一步。我投反对票。
  2. 如果我们有延迟加载导致难以进行单元测试,那么就一直返回 IQueryable。您将拥有更多的控制权。我仍然认为这不是一个好的选择,因为 IQueryable 将您与 L2S、L2E 或您自己的 IQueryable 完整实现联系在一起。延迟加载可能会“按需”运行查询,但不会将您绑定到任何特定界面。我投反对票。
  3. 关闭延迟加载。您必须手动处理您的关联。这可能是急切加载的 .Include()。在某些特定情况下,我投赞成票。
  4. 保持 IList 和延迟加载。我在很多情况下都投赞成票,只是因为与其他人的麻烦。

还有其他选择或建议吗?我还没有找到真正让我信服的选项。

【问题讨论】:

    标签: entity-framework lazy-loading data-layers


    【解决方案1】:

    你可以让你的方法接受某种加载策略。

    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

    【讨论】:

    • 您没有涵盖“从 UI 层延迟加载/SQL 执行”,但这仍然有帮助。我认为最后一段代码最接近我正在寻找的内容。看起来您具有 1) 易用性,2) 封装/SoC/可单元测试/等,3) 使用高级功能(急切加载等)的能力。选择两个。你不能同时拥有这三个。无论如何,谢谢你的帮助。
    猜你喜欢
    • 1970-01-01
    • 2014-04-01
    • 2018-06-24
    • 2016-12-14
    • 2019-02-12
    • 2012-02-15
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    相关资源
    最近更新 更多