【问题标题】:Linq select all numbers that are in any interval from another list of intervalsLinq从另一个间隔列表中选择任何间隔中的所有数字
【发布时间】:2017-06-21 10:08:44
【问题描述】:

我正在尝试编写 linq lambda select 以从数据库中获取所有记录,这些记录具有来自其他列表或数据库表的任何特定间隔中的数字。假设我有一张桌子“SOURCE” +------+------+-------+------+------+ | Col1 | Col2 | reqNr | col5 | col6 | +------+------+-------+------+------+ | x | x | 9 | x | x | | x | x | 14 | x | x | | x | x | 19 | x | x | | x | x | 24 | x | x | +------+------+-------+------+------+ 我已经选择了表格“INTERVALS” +------+----+ | from | to | +------+----+ | 1 | 3 | | 5 | 10 | | 15 | 30 | +------+----+ 到 c# 中的对象列表“intervalList”。 如何在 linq sql 语句中编写“.Where()”部分以从“SOURCE”中获取所有记录,这些记录具有“ReqNr”列值,该值属于“intervalList”列表中的任何间隔。 例如:.where(w => intervalList.any(w.ReqNr > intervalList.from && w.ReqNr < intervalList.to))

【问题讨论】:

    标签: c# sql .net linq lambda


    【解决方案1】:

    你可以这样做:

    var result = iRec
      .Where(r => intervalList.Any(i => i.From <= r.reqNr && i.To >= r.reqNr))
      .ToList();
    

    您可以查看here

    【讨论】:

      【解决方案2】:

      将 where 和 Any 作为内部谓词应用于 where 方法,如下所示:

      var result = SOURCE
        .Where(d => INTERVALS.Any(e => e.from<d.reqNr && e.to>d.reqNr))
        .ToList();
      

      【讨论】:

        【解决方案3】:

        据我了解您的问题,您需要在数据库端执行查询,intervals 列表是内存中的列表。

        您需要一个如下所示的 SQL 查询:

        SELECT * FROM SOURCE WHERE 
            ((1 < reqNr) AND (3 > reqNr))
            OR ((5 < reqNr) AND (10 > reqNr))
            OR ((15 < reqNr) AND (30 > reqNr))
        

        如您所见,查询本身是动态的。 OR 条件的数量和内容取决于区间列表(内存中的列表)。

        要生成这样的动态查询,您需要动态构建Expression&lt;Func&lt;Item,bool&gt;&gt; 并将其传递给Where 方法。 (Item 是 Source 表的实体名称)。

        您可以使用LinqKit 来创建这样的动态表达式:

        Expression<Func<Item, bool>> condition =
            intervals
                .Select(
                    interval =>
                        (Expression<Func<Item, bool>>)
                            (x => interval.From < x.reqNr && interval.To > x.reqNr))
                .Aggregate(LinqKit.PredicateBuilder.Or);
        
        var result = context.SourceTable
            .Where(condition)
            .ToList();
        

        顺便说一下,这个解决方案之所以复杂,只是因为区间列表在内存中。一个更简单的解决方案是直接使用存储在数据库中的间隔来查询数据库,如下所示:

        var result =
            context.SourceTable
                .Where(x =>
                    context.Intervals.Any(interval =>
                        interval.From < x.reqNr && interval.To > x.reqNr))
                .ToList();
        

        【讨论】:

        • 感谢您的详细解释。但在我看来,第二部分就足够了。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-10
        • 1970-01-01
        • 1970-01-01
        • 2021-09-08
        • 1970-01-01
        • 2016-05-17
        • 1970-01-01
        相关资源
        最近更新 更多