linq dotnet中日期范围之间的日期和时间

wkyowqbh  于 2022-12-06  发布在  其他
关注(0)|答案(1)|浏览(190)

I am facing the problem to know if DateTime is between a date range in the dotnet.
For example if the x.SchedulerStart value is 2022-11-02 06:46:30 and x.SchedulerEnd value is 2022-11-02 23:26:30 . I want check this DateTime.Today value is inside the date range, but below coding is doesn't work. I have look at this StackOverflow question still cannot work How to know if a DateTime is between a DateRange in C#
Below is my coding:

x.SchedulerStart.Date >= DateTime.Today && x.SchedulerEnd.Date <= DateTime.Today

Whole code:

List<SAASMsgSchedulerForQueueList> msgSchedulerList = await _saasdbContext.SaMsgScheduler.AsNoTracking().Where(x => (x.Enabled == true && x.SchedulerStart.Date >= DateTime.Today && x.SchedulerEnd.Date <= DateTime.Today) &&
    ((x.SchedulerRecurring == "Daily" && x.RecurringTime == currentTime) || (x.SchedulerRecurring == "Weekly" && x.RecurringWeekday == weekDayNumber && x.RecurringTime == currentTime) ||
    (x.SchedulerRecurring == "Monthly" && x.RecurringDay == currentDay && x.RecurringTime == currentTime) || (x.SchedulerRecurring == "Yearly" && x.RecurringMonth == currentMonth && x.RecurringTime == currentTime)))
    .Join(_saasdbContext.TnMsgTemplate.AsNoTracking(),
    schedule => schedule.TemplateId,
    template => template.Id,
    (schedule, template) => new { schedule, template })
    .Join(_saasdbContext.SaMsgQuery.AsNoTracking(),
    schedule => schedule.template.QueryId,
    query => query.Id,
    (schedule, query) => new SAASMsgSchedulerForQueueList()
    {
        ID = schedule.schedule.Id,
        BranchID = schedule.schedule.BranchId,
        TemplateID = schedule.schedule.TemplateId,
        TemplateContent = schedule.template.TemplateContent,
        Query = query.QuerySql,
        MessageType = schedule.schedule.MessageType,
        RecurringDatetime = schedule.schedule.RecurringDatetime,
    }).ToListAsync();

Hope some one can guide me on how to solve this problems. Thanks.

rwqw0loc

rwqw0loc1#

你需要把情况反过来。现在你要找的是从今天之后开始到今天之前结束的东西。
最好以反映您所需内容的形式编写查询,即“今天”介于开始日期和结束日期之间:

x.SchedulerStart.Date <= DateTime.Today && DateTime.Today <= x.SchedulerEnd.Date

更好的是,如果我把字段放在这样一个查询的左边,20年后我仍然会把事情搞混。
另一个改进是避免.Date。这会在SQL Server中产生cast(ScheduleStart as date)。通常,这样的转换会阻止索引的使用。SQL Server很聪明,可以将其转换为范围查询,但不能使用为ScheduleStart列收集的任何索引,这样仍然会导致执行计划效率低下。
.Date可以简单地从DateTime.Today <= x.SchedulerEnd.Date中删除。如果结束日期是今天,则DateTime.Today <= x.SchedulerEnd在任何时间都有效。
若要将.Date从开始日期中剔除,请将其与第二天(即x.SchedulerStart < DateTime.Today.AddDays(1))进行比较。如果开始日期是今天,则每次都保持该值。如果SchedulerStart是第二天,则条件仍为false。
正确有效的条件是:

x.SchedulerStart < DateTime.Today.AddDays(1) 
&& DateTime.Today <= x.SchedulerEnd

该查询针对的是使用Oracle官方EF Core提供程序MySQL.EntityFrameworkCore的MySQL,它有几个已知的问题,这些问题都在Oracle自己的时间表中得到了修复。这就是为什么几乎所有人都使用真正开源的Pomelo.EntityFrameworkCore.MySql。每个人都像Pomelo的下载量为2930万,而Oracle的提供程序的下载量为170万。
在这种情况下,Oracle提供程序无法将DateTime.Today.AddDays(1)视为常量,并尝试将其转换为SQL表达式。
要避免此问题,请在查询之前计算日期,例如:

var today    = DateTime.Today;
var tomorrow = today.AddDays(1);

...
x.SchedulerStart < tomorrow && today <= x.SchedulerEnd

相关问题