【问题标题】:Working around LinqToSQls "queries with local collections are not supported" exception解决 LinqToSQls“不支持使用本地集合的查询”异常
【发布时间】:2009-07-05 16:14:49
【问题描述】:

所以,我试图返回一个 ID 包含在本地创建的 ID 集合 (IQueryable) 中的 People 集合

当我指定“本地创建的集合”时,我的意思是 Ids 集合不是来自 LinqToSql 查询,而是以编程方式创建的(基于用户输入)。 我的查询如下所示:

var qry = from p in DBContext.People
                  where Ids.Contains(p.ID)
                  select p.ID;

这会导致以下异常...

“不支持使用本地集合的查询”

如何找到所有具有包含在本地创建的 Ids 集合中的 ID 的人?

是否可以使用 LinqToSql?

【问题讨论】:

    标签: linq-to-sql collections


    【解决方案1】:

    如果 Ids 是 List、数组或类似的,L2S 将转换为 contains。

    如果 Ids 是 IQueryable,只需将其转换为列表,然后在查询中使用它即可。例如:

    List<int> listOfIDs = IDs.ToList();  
    var query =  
    from st in dc.SomeTable  
    where listOfIDs.Contains(st.ID)
    select .....
    

    【讨论】:

    • 我认为您的问题的解决方案比这个答案更微妙。我成功地使用了相同的构造(WHERE 子句中 IQueryable 上的 Contains 方法),并且 LINQ to SQL 将其转换为 SQL 查询中的 WHERE EXISTS 子句。它似乎在某些情况下有效,但在其他情况下无效,因此您应该发布如何获得 IQueryable 的 Ids,因为这可能会阐明这个问题。
    • @jmbledsoe 如果我的回答不够清楚:L2S 期望将本地 IEnumerable(不是延迟的 IQueryable)传递给 Enumerable.Contains。如果您将其传递给本地查询,则无法将其转换为 SQL 查询。如果你给它传递一个列表/数组/等,那么它可以被翻译成一个 SQL “where ... in (x, y, ..., n)”子句。
    • 我想我明白你在说什么: - 传递一个列表/数组/等。没问题 b/c 它将生成一个 WHERE ... IN 子句。 - 传递一个延迟的 IQueryable 是好的 b/c 它将与当前的延迟查询集成。 - 传递一个本地 IEnumerable 是不行的,但你可以 .ToList() 它就可以了。
    • 及早解决您的 IQueryables 可能会导致严重的性能损失。首先尝试使用 Any() 而不是 Contains()。
    • 如果 listOfIDs 是数百或数千个项目,您可能需要检查 @maxlego 对我有用的答案
    【解决方案2】:

    我也在努力解决这个问题。解决了我使用 Any() 代替的问题

    people.Where(x => ids.Any(id => id == x.ID))
    

    【讨论】:

    • @maxlego 并且生成的SQL是descent。谢谢
    【解决方案3】:

    如上所述,将 IQueryable 类型的 id 转换为 List 或 Array 将解决问题,这将在 SQL 中转换为“IN”运算符。但是要小心,因为如果 id 的计数 >= 2100 这将导致另一个问题,即“服务器最多支持 2100 个参数”,这是您可以在 SQL 服务器中传递给“IN”的最大参数(值)数。

    另一种选择是将 id 保持为 IQueryable 并使用 LINQ“Any”运算符而不是“Contains”,这将在 SQL Server 中转换为“EXISTS”。

    【讨论】:

      【解决方案4】:

      很抱歉,这里的答案对我不起作用,因为我正在进一步做动态类型。

      我所做的是在一个效果很好的循环中使用“UNION”。方法如下:

      var firstID = cityList.First().id;
      var cities = dc.zs_Cities.Where(c => c.id == firstID);
      foreach(var c in cityList)
      {
        var tempCity = c;
        cities = cities.Union(dc.zs_Cities.Where(cty => cty.id == tempCity.id));
      }
      

      【讨论】:

        猜你喜欢
        • 2011-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-13
        相关资源
        最近更新 更多