【问题标题】:Search by Date using Linq query使用 Linq 查询按日期搜索
【发布时间】:2015-09-23 06:11:02
【问题描述】:

我有数据库表,它有一个字段调用 CreatedDate 这是日期时间格式。

例如:在该字段中的值保存为 2015-08-27 13:28:50.333NULL

我写了以下 Linq 查询以通过 typecategorycountrysubsidary 和 date 进行搜索。 typecategorycountrysubsidary 字段为 nvarchar 字段,日期为 DateTime 字段

    [HttpGet]
    public JsonResult FetchProducts(string type, string category, string country, string subsidary, string dateHERE)
    {

        DateTime? mydate = null;
        DateTime date2;
        bool check = DateTime.TryParse(dateHERE, out date2);
        if (check)
        {
            mydate = date2;
        }

        ................


        if (!string.IsNullOrWhiteSpace(type))
            products = products.Where(p => p.ProductType_ID.StartsWith(type));

        ....................

        if (check)
        {
           products = products.Where(p => p.CreatedDate.Equals(mydate)).ToList();
        }

        ...............

        return Json(data, JsonRequestBehavior.AllowGet);
    }

一旦我输入日期并搜索,我就会得到空值

此查询适用于除 date 之外的几乎所有字段。什么是正确的 linq 查询来搜索日期。

【问题讨论】:

  • 步骤 1. 将您的参数更改为 DateTime dateHERE 并删除您解析它的代码。
  • 您的日期以毫秒为单位存储,因此您不太可能使用 .Equals() 找到完全匹配的日期。
  • @StephenMuecke 我将参数更改为DateTime? dateHERE,将linq 查询更改为if (dateHERE.HasValue) products = products.Where(p => p.CreatedDate.Equals(dateHERE)).ToList();,但结果相同
  • 正如我之前提到的,您的dateHERE 值不太可能将现有记录之一匹配到最接近的毫秒。最好的猜测是你想要.Where(p => p.CreatedDate > d1 && p.CreatedDate < d2) d1 = dateHERE.Date()d2 = d1.AddDays(1)
  • 在这种情况下,将其设为.Where(p => p.CreatedDate >= d1 && p.CreatedDate < d2) - 请注意>= d1 - 因此它包含带有2015-08-27 00:00:00.000 的日期。 @GertArnold 已经给出了答案,所以你可以接受

标签: c# json asp.net-mvc linq datetime


【解决方案1】:

你必须截断时间:

 ...products.Where(p => EntityFunctions.TruncateTime(p.CreatedDate) == mydate)

如果您使用的是 EF6,请将 EntityFunctions 更改为 DbFunctions

其他信息:

EntityFunctions 方法称为规范函数。这些是一组功能,所有实体框架提供者都支持这些功能。这些规范函数将被转换为提供者的相应数据源功能。规范函数是访问核心语言之外的功能的首选方式,因为它们保持查询的可移植性。

您可以找到所有规范函数 here 以及所有日期和时间规范函数 here

别忘了添加对System.Data.ObjectsSystem.Data.Entity的引用。

或者另外您可以使用该逻辑截断时间部分:

DateTime? myDateTomorrow = myDate;
myDateTomorrow.Value.AddDays(1);

products.Where(p => p.CreatedDate >= mydate && p.CreatedDate < myDateTomorrow);

【讨论】:

  • 一旦我把那个products = products.Where(p =&gt; DbFunctions.TruncateTime(p.CreatedDate) = mydate); 得到这个错误The left-hand side of an assignment must be a variable, property or indexer
  • @kez 将= 替换为==.Equals()
  • 我整合了您的第一个解决方案,但结果相同,然后尝试第二个解决方案在AddDays 下获得红色摆动线
  • @kez 我没注意DateTime?。用myDate.Value 更新了我的代码
  • 我整合了第二个,现在我得到了整个数据集,但它没有按日期过滤,现在该怎么办
【解决方案2】:

因为这里的每个人都已经提到你的日期 .Equals() 因为毫秒而不起作用,所以我通常使用 DateTime 类的 Date 属性,它只获取数据时间对象的日期部分,所以我建议你这样做:

if (check)
{
    products = products.Where(p => p.CreatedDate != null //check on null
    && p.CreatedDate.Value.Date == mydate).ToList();
}

【讨论】:

    【解决方案3】:

    如果您的查询来自 SQL 后端,您必须始终牢记,数据库引擎应该能够将生成的 SQL 转换为有效的执行计划。因此,要查看的一个重要因素是索引使用情况。如果在谓词中使用数据库字段之前对其进行转换,则该字段上的任何索引都将被禁用:

    WHERE dateField = date -- index on dateField can be used
    

    对比

    WHERE DATEPART(.. dateField ..) = date -- index can't be used
    

    所以最好进行范围检查:

    ...
    mydate = date2.Date;
    ...
    
    
    if (mydate.HasValue)
    {
       var mydatePlus = mydate.Value.AddDays(1);
       products = products.Where(p => p.CreatedDate >= mydate && p.CreatedDate < mydatePlus)
                          .ToList();
    }
    

    这也称为 sargable 表达式。

    【讨论】:

      【解决方案4】:

      其他更敏捷的方式...

      Expression<Func<Products, bool>> expresionFinal = p => p.Active;
      
      if (mydate.HasValue)
      {
          Expression<Func<Products, bool>> expresionDate = p => (EntityFunctions.TruncateTime(c.CreatedDate) <= mydate);
          expresionFinal = PredicateBuilder.And(expresionFinal, expresionDate );
      }
      
      IQueryable<T> query = dbSet;
      
      
          query = query.Where(expresionFinal);
      

      【讨论】:

      • 只有&lt;= mydate 给出错误的结果。不要只是假设每个人都知道 PredicateBuilder。
      • 为什么错误的结果?我们搜索作品,结果在 mydate 之前或同一天。
      【解决方案5】:

      我正在使用此 linq 查询在日期列中进行搜索:

      var list = db.records;
      DateTime? date_start;
      
      if (date_start != null)
      {
         list = list.Where(x => x.date != null &&
         x.date.Value.Date >= date_start.Value.Date);
      }
      

      这将返回日期 >= date_start 的所有记录

      【讨论】:

        猜你喜欢
        • 2017-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-24
        • 1970-01-01
        相关资源
        最近更新 更多