The problem with something like
DateTime today = DateTime.Today ;
Context.Records.Where(r => EntityFunctions.TruncateTime(r.CreationDate) == today) ;
is that underlying SQL is likely going to look something like this:
select *
from some_table r
where convert(date,r.CreationDate) == @today
Since the column is now a part of an expression, the SQL engine is unable to make use of any covering indices it has available. Unless you've got other criteria that will use indices, you're going to table scan. And with big tables, that will cause performance issue.
And you should avoid the obvious
DateTime today = DateTime.Today ;
DateTime dayEnd = today.AddDays(1).AddMilliseconds(-1);
context.Records.Where(r => r.CreationDate >= today && r.CreationDate <= dayEnd) ;
because of the way SQL Server datetime
values work: while they count in milliseconds, SQL Server's 'ticks' occur in 3- and 4-millisecond increments. For details, see my answer to the question How does SqlDateTime do its precision reduction. But in a nutshell:
To do the conversion in the manner in which SQL Server does it, do the following:
Take the milliseconds portion of the actual time under consideration, a value from 0-999,
modulo 100. That gives you the low order digit, a value from 0-9. So if the current time
is 23:57:23.559, the milliseconds component is 559. Modulo 100 you get 9.
- Values 0 and 1 are "rounded down" to 0.
- Values 2, 3 and 4 are "rounded down"" to 3.
- Values 5, 6, 7 and 8 are "rounded down" to 7.
- A value of 9 is rounded UP to 0. This has a rather unpleasant and nasty side
effect: if the milliseconds portion of the time is 999, it ticks up 1 millisecond. This
means that the time 23:59:59.999 is rounded up to THE NEXT DAY. So conversion of '31
Dec 2010 23:59:59.999' yields a datetime value of...1 January 2011 00:00:00.000.
Note that smalldatetime
also exhibits this kind of behavior. Only datetime2
is exempt.
So...
Unless you're careful, it's really easy to drop things on the floor that have been timestamped right at end-of-day (don't ask how I know this).
You're better off doing something like
DateTime today = DateTime.Today ;
DateTime tomorrow = today.AddDays(1);
context.Records.Where(r => r.CreationDate >= today && r.CreationDate < tomorrow) ;
which should translate into SQL that looks something like
select *
from some_table r
where r.CreationDate >= @today
and r.CreationDate < @tomorrow
and will allow the optimizer to make use of indices on the date/time column.