简体   繁体   中英

Can anyone convert this SQL query into a C# Linq statement?

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?

Answer

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.

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;}
}

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.

    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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM