【问题标题】:How to search date in a dynamic query using IQueryable in c#如何在 C# 中使用 IQueryable 在动态查询中搜索日期
【发布时间】:2021-07-16 17:36:41
【问题描述】:

我需要在 sql server 数据库表中搜索。我正在使用IQueryable 构建如下动态查询

var searchTerm = "12/04";      
var samuraisQueryable = _context.Samurais.Include(x => x.Quotes).AsQueryable();
samuraisQueryable = samuraisQueryable.Where(x => x.Name.Contains(searchTerm) ||
                                                    x.CreatedDate.HasValue && x.CreatedDate.Value.ToString()
                                                        .Contains(searchTerm)

var results = samuraisQueryable.ToList();

上面的查询只是一个例子,我的代码中的实际查询是不同的,更复杂。

Samurai.cs 看起来像

public class Samurai
{

    public Samurai()
    {
        Quotes = new List<Quote>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime? CreatedDate { get; set; }
    public List<Quote> Quotes { get; set; }
}

表格中的数据看起来像

我看不到任何结果,因为上述查询中的已翻译 SQL 将日期转换为不同的格式 (CONVERT(VARCHAR(100), [s].[CreatedDate]))。我尝试在上述查询中指定日期格式,但随后出现 The LINQ expression cannot be translated 错误。

samuraisQueryable = samuraisQueryable.Where(x => x.Name.Contains(searchTerm) ||
                                                         x.CreatedDate.HasValue && x.CreatedDate.Value.ToString("dd/MM/yyyy")
                                                            .Contains(searchTerm)

【问题讨论】:

  • 从 DateTime 对象中删除问号。 c# 不支持 DateTime 的空值。
  • Queryable 将在服务器端进行评估,因此您无法执行 ToString().Contains(...)。要么您必须先执行ToList() 并在客户端对其进行评估,要么您必须先更改表达式以不使用Contains(),例如`x.C​​reatedDate.Value == yourDateTimeObjectHere. So you might have to use DateTime.TryParse`如果它甚至是一个有效的日期。
  • @Fred 我同意你的观点,但问题是用户会部分搜索像“12/04”这样的日期而不是“12/04/2021”(我可以解析并做一个相等的检查)他们会期待对此进行过滤。

标签: c# linq iqueryable


【解决方案1】:

如果(cmets)用户想要部分搜索日期,那么老实说:最好的办法是让您的代码检查他们的输入,并将其解析为范围查询。所以;如果您看到"12/04",您可能会将其解析为一天(在当年,应用您选择的 dd/mm 与 mm/dd),然后在 >= 当天和 "2021",您的代码 应该执行相同的操作,但作为范围查询。尝试进行简单的部分匹配不仅计算成本高(并且难以编写为查询):它对用户也不是很有用。例如,仅在 "2" 上搜索 - 作为“包含”查询没有意义。

那么你拥有的是:

(var startInc, var endExc) = ParseRange(searchTerm);
samuraisQueryable = samuraisQueryable.Where(
    x => x.CreatedDate >= startInc && x.CreationDate < endExc);

【讨论】:

    猜你喜欢
    • 2020-08-20
    • 2017-09-14
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 2016-07-29
    相关资源
    最近更新 更多