Reputation: 75
I have a SQL query which is as follows:
SELECT [ClientId]
,[LastDelivery]
,[LastRequisitionDate]
,Datediff (day, LastRequisitionDate, LastDelivery) as DiffDate
FROM [dbo].[App_Client]
where (LastDelivery != '1900-01-01 00:00:00'
and LastRequisitionDate != '1900-01-01 00:00:00')
and Inactive = 0
and (Datediff (day, LastRequisitionDate, LastDelivery) < 9)
and (Datediff (day, LastRequisitionDate, LastDelivery) >= 0)
I have a list of clients, and I want all clients who received their delivery within 8 days of their requisition. The reason for the
LastDelivery != '1900-01-01 00:00:00'
and LastRequisitionDate != '1900-01-01 00:00:00'
is because the way I have my c# query requires that there are no null fields in any of the date fields(those fields are nullable in the DB but they really shouldn't be). I have a DB containing 11838 clients, and this query returns 10404. My problem is I have been unable to duplicate this query with C# linq.
My C# query is as follows:
var clients = _clientService.GetAllClients().Where(x =>
(x.LastDelivery != Convert.ToDateTime("01/01/1900")
&& x.LastRequisitionDate != Convert.ToDateTime("01/01/1900"))
&& x.Inactive == 0
&& (((DateTime)x.LastDelivery - (DateTime)x.LastRequisitionDate).Days < 9)
&& (((DateTime)x.LastDelivery - (DateTime)x.LastRequisitionDate).Days >= 0)).ToList();
This query returns 10563 results, a difference of 159, and I cannot figure out at all where I'm going wrong. To me that C# query looks identical to the SQL one, but somewhere there is a discrepancy. I've been coding all day, so maybe I'm a bit burnt out and the solution is obvious, but I just can't see it. Can anyone help, or suggest what I may be doing wrong or overlooking?
As correctly pointed below by Matt Smith, it turns out both queries were correct - the discrepancy lay in the SQL DateDiff function, which measures 1 day as when the day passes midnight, which means comparing 01/01/2016 23:59:59 and 01/02/2016 00:00:01 gives a difference of one day, whereas in my C# query, it was comparing actual difference in days as a timespan (24hrs). Great find and important distinction to be made, thanks to Matt Smith.
Upvotes: 0
Views: 209
Reputation: 636
Do you have time components in your date values? If so, there are important differences between the way DateDiff works in SQL, where DateDiff(day, '03/06/2016 23:59:59', '03/07/2016 00:00:01') = 1, and .NET where ('03/07/2016 23:00:00' - '03/06/2016 23:59:00').Days = 0. DateDiff(day,x,y) measures the number of Day boundaries crossed. In .NET, the subtraction of DateTimes returns a TimeSpan of days, hours, minutes, seconds, milliseconds, and TimeSpan.Days returns the number of days in the TimeSpan.
Upvotes: 2
Reputation: 24
var clients = (from a in _clientService.GetAllClients().ToList()
where
(a.LastDelivery != DateTime.Parse("1900-01-01 00:00:00")
&&
a.LastRequisitionDate != DateTime.Parse("1900-01-01 00:00:00"))
&& ((a.LastRequisitionDate - a.LastDelivery).Days < 9)
&& ((a.LastRequisitionDate - a.LastDelivery).Days >= 0)
&& a.Inactive == 0
select a).ToList();
Upvotes: 1
Reputation: 1944
Since I don't have your data, I can't be sure this works, but give this a go. It should at least give you something to go with
var clients = (from client in _clientService.GetAllClients()
let minDate = DateTime.MinValue
let lastRequisitionDate = (DateTime)client.LastRequisitionDate
let lastDeliveryDate = (DateTime)client.LastDeliveryDate
let lastDelivery = (DateTime)client.LastDelivery
where lastRequisitionDate != minDate && lastDelivery != minDate && client.Inactive != 0 && (lastDelivery - lastRequisitionDate).Days < 9 && (lastDelivery - lastRequisitionDate).Days >= 0
select client).ToList();
You can also potentially make things easier on yourself by changing your Client
entity to allow for nullable dates:
public class Client
{
public DateTime? LastRequisitionDate {get; set;}
}
Upvotes: 2