Linq to SQL 选择 DateTime 字段在任何日期范围列表中的行

Posted

技术标签:

【中文标题】Linq to SQL 选择 DateTime 字段在任何日期范围列表中的行【英文标题】:Linq to SQL to select rows whose DateTime field falls within any of a list of date ranges 【发布时间】:2013-10-25 15:26:56 【问题描述】:

我有一个包含 StartDate 和 EndDate 属性的 DateRange 对象列表。我需要从我的数据库中的表中选择所有行,这些行的 DateTime 字段属于这些 DateRanges 中的任何一个。所以我想做这样的事情:

// Using an IQueryable<DateRange> called dateRanges
var tests = from test in dbContext.Tests
            where dateRanges.Any(range => range.StartDate <= test.Date && range.EndDate >= test.Date)
            select test

这给了我一个错误,因为 DateRange 不是原始类型,因此 LINQ to SQL 无法使用它。有没有其他方法可以做我在这里想做的事情?几个小时以来一直在谷歌搜索和尝试不同的事情,我觉得我很接近但不能完全到达那里。提前致谢。

【问题讨论】:

我对@9​​87654322@ 不太满意,但你能比较一下他们的.Ticks 的价值吗? 好吧,问题不在于比较 DateTime 值,而是 DateRange 不是原始类型,因此它不能被转换为 SQL 可以使用的任何内容以使操作发生服务器端。 你可以建立一个 TSQL 查询来代替吗? @Malleus 对我来说有点奇怪,可以试试dateRanges.Any(x=&gt;true)吗? 您的 StartDate 和 EndDate 属性是什么类型的? 【参考方案1】:

尝试使用 Linq2Sql 与动态查询类似

(p => value1.StartDate <= p.Date && value1.EndDate >= p.Date) || (p => value2.StartDate <= p.Date && value2.EndDate >= p.Date)

示例:Linq2SQL "or/and" operators (ANDed / ORed conditions)

【讨论】:

【参考方案2】:

为了保证没有不必要的数据被传输,我决定这样做的方法是在我的数据库上创建一个名为 GetTestsInDateRange 的存储过程,它接受开始和结束日期并返回其中的所有测试范围。然后在我的代码中,我循环遍历我的 DateRanges 列表,为每个 DateRange 调用一次存储过程,并将结果合并在一起。

IEnumerable<Test> tests = new List<Test>();
foreach (DateRange range in selectedDateRanges)

    tests = tests.Union(dbContext.GetTestsInDateRange(range.StartDate, range.EndDate));

我不知道这是否是理想的解决方案(可能取决于选择了多少 DateRanges 以及它对数据库进行了多少单独调用),但它适用于我的场景。

【讨论】:

【参考方案3】:

通过连接每个范围的条件来制作您自己的 SQL 语句,部分限制您返回的结果的一种方法是使用范围的最小和最大日期,然后在 Linq-To-Objects 中进一步过滤:

var minStartDate = dateRanges.Min(r => r.StartDate);
var maxEndDate = dateRanges.Max(r => r.EndDate);
var tests = (from test in dbContext.Tests
            where minStartDate <= test.Date && maxEndDate >= test.Date
            select test)
            .AsEnumerable()  // change to Linq-To-Objects
            .Where(test => dateRanges.Any(range => range.StartDate <= test.Date 
                                                   && range.EndDate >= test.Date));

这对于一个范围来说是完美的,除非你的范围之间有很大的差距,否则只会稍微差一点。

【讨论】:

如果您要比较大量数据,将所有数据全部取走,然后使用 linq2objects,这不是一个好主意。会杀死你的服务器

以上是关于Linq to SQL 选择 DateTime 字段在任何日期范围列表中的行的主要内容,如果未能解决你的问题,请参考以下文章

不支持 Linq-to-EF DateTime.ToLocalTime

LINQ体验(11)——LINQ to SQL语句之Null语义和String/DateTime方法

Linq to sql 有将datetime转换为string类型方法吗

Linq to SQL DateTime 值是本地的(Kind=Unspecified)-如何使它成为 UTC?

使用Linq to SQL加载DataGridView

Linq To Sql 仅比较时间