【问题标题】:Can anyone convert this SQL query into a C# Linq statement?任何人都可以将此 SQL 查询转换为 C# Linq 语句吗?
【发布时间】:2016-03-09 04:48:07
【问题描述】:

我有一个 SQL 查询如下:

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)

我有一份客户名单,我希望所有客户在申请后 8 天内收到货。原因

LastDelivery != '1900-01-01 00:00:00' 
and LastRequisitionDate != '1900-01-01 00:00:00'

是因为我的 c# 查询方式要求任何日期字段中都没有空字段(这些字段在数据库中可以为空,但它们确实不应该)。我有一个包含 11838 个客户端的数据库,此查询返回 10404。我的问题是我无法使用 C# linq 复制此查询。

我的 C# 查询如下:

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

这个查询返回 10563 个结果,相差 159,我根本不知道哪里出错了。对我来说,C# 查询看起来与 SQL 查询相同,但在某处存在差异。我整天都在编码,所以也许我有点筋疲力尽,解决方案很明显,但我就是看不到。谁能提供帮助或建议我可能做错了什么或忽略了什么?

回答

正如马特史密斯在下面正确指出的那样,事实证明这两个查询都是正确的 - 差异在于 SQL DateDiff 函数,它测量 1 天,当一天经过午夜时,这意味着比较 2016 年 1 月 1 日 23:59 :59 和 01/02/2016 00:00:01 给出了一天的差异,而在我的 C# 查询中,它将天数的实际差异作为时间跨度(24 小时)进行比较。多亏了马特·史密斯,伟大的发现和重要的区别。

【问题讨论】:

  • 那么,将生成的 SQL 与您的原始 SQL 进行比较。
  • 我不知道该怎么做...
  • 您正在使用 EntityFramework 或其他类似的基于 IQueryable 的系统吗?如果您可能希望将此过滤器移动到“调用堆栈的较低位置”,您似乎正在使用IEnumerable,因为您执行的操作在 EF 中是不允许的,因此您的数据库正在使用没有过滤器,返回所有行,然后你在内存中过滤,这会给你带来糟糕的性能。
  • 您的日期值中有时间组件吗?如果是这样,则 DateDiff 在 SQL 中的工作方式之间存在重要差异,其中 DateDiff(day, '03/06/2016 23:59:59', '03/07/2016 00:00:01') = 1 和.NET 其中 ('03/07/2016 23:00:00' - '03/06/2016 23:59:00').Days = 0。DateDiff(day,x,y) 测量跨越的 Day 边界数. TimeSpan.Days 返回差异的天数部分。
  • 好的,我已经把它作为答案发布了。 @ailinmcc666,要检查一下吗?

标签: c# sql linq


【解决方案1】:

您的日期值中有时间组件吗?如果是这样,则 DateDiff 在 SQL 中的工作方式之间存在重要差异,其中 DateDiff(day, '03/06/2016 23:59:59', '03/07/2016 00:00:01') = 1 和.NET 其中 ('03/07/2016 23:00:00' - '03/06/2016 23:59:00').Days = 0。DateDiff(day,x,y) 测量跨越的 Day 边界数.在 .NET 中,DateTimes 的减法返回由天、小时、分钟、秒、毫秒组成的 TimeSpan,而 TimeSpan.Days 则返回 TimeSpan 中的天数。

【讨论】:

    【解决方案2】:

    由于我没有您的数据,我无法确定这是否有效,但请试一试。它至少应该给你一些东西

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

    您还可以通过更改您的 Client 实体以允许可以为空的日期来使事情变得更轻松:

    public class Client
    {
        public DateTime? LastRequisitionDate {get; set;}
    }
    

    【讨论】:

    • 感谢回复,试过了,还是不行:(
    • 如抛出异常不起作用,或“起作用”但仍返回错误数量的客户端?
    • 抱歉 - 它成功了,但返回的金额仍然不正确。
    • 奇数。如果您确实确定数字不正确,正如@ailinmcc666 提到的那样,它可能只会为您节省更多时间来使用存储过程
    • 查看上面 Matt Smith 的评论,他似乎发现了问题所在。
    【解决方案3】:
        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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多