【问题标题】:How to avoid converting iQueryable to a List?如何避免将 iQueryable 转换为列表?
【发布时间】:2015-07-17 11:33:07
【问题描述】:

我有以下(工作)代码:

 List<Location> allLocations = new List<Location>();
 using (MyContext context = new MyContext())
 {
     Login currentLogin = GetCurrentLogin(context);
     if (currentLogin != null)
     {
         foreach (var customer in currentLogin.Customers)
         {
             allLocations.AddRange(customer.Locations);
         }
     }
 }
 return allLocations.AsQueryable();

MyContext 及其对象存在于实体框架中。 CustomersLocationsICollection&lt;&gt;-属性

此代码按预期工作,返回用户客户的所有位置

但如您所见,我将实体 customer.Locations 添加到 List

在该函数结束时,我将生成的列表返回为IQueryAble,以便能够继续在结果上使用LinQ-Expressions。

由于性能原因,我想跳过列表-步骤并留在IQueryAble

有可能吗?

【问题讨论】:

  • 你为什么要返回IQueryable&lt;T&gt;?您可以在 List&lt;T&gt; 上使用 LINQ 表达式就好了。当然,它们都将在内存列表中工作,而不是进入数据库,但你当前的代码也不会有任何不同。
  • 这就是我不喜欢我的代码的原因,这就是我所说的“性能原因”

标签: c# linq entity-framework iqueryable


【解决方案1】:

使用SelectMany 在没有foreach 循环的情况下完成整个事情怎么样?这样您就可以将所有内容保留为IEnumerable

using (MyContext context = new MyContext())
{
    Login currentLogin = GetCurrentLogin(context);
    if (currentLogin != null)
    {
        return currentLogin.Customers.SelectMany(c => c.Locations);
    }
}

【讨论】:

    【解决方案2】:

    List&lt;Location&gt; allLocations 更改为IQueryable&lt;Location&gt; allLocations

    然后您可以执行allLocations = currentLogin.Customers.SelectMany(c =&gt; c.Locations).AsQueryable() 之类的操作。

    【讨论】:

      【解决方案3】:

      在处理 MyContext() 后,我会小心使用 IQueryAble 或 IEnumerable,因为它们是延迟加载的。

      在调用它的任何函数中使用查询之前,它实际上不会被评估,但到那时,上下文将被释放,并且将引发异常。

      这可能是该方法最初将返回结果填充到 List 中的原因,因为它强制在上下文仍处于活动状态时评估查询。

      【讨论】:

      • 你说得对。我已经更改了方法并使用上下文作为方法参数。
      • 很高兴听到。请注意,根据我的经验,上下文保存的时间越长,它的速度就越慢,尤其是在您进行更新和插入时。
      猜你喜欢
      • 2020-01-10
      • 2011-04-19
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多