【问题标题】:Linq where condition on datetime.ToString()Linq where datetime.ToString() 的条件
【发布时间】:2018-08-02 11:17:58
【问题描述】:

我有以下 Linq 代码

// query = IQueryable<DataClass>
query = query.Where(m => m.Column1.Contains(model.search.value)
        || m.DateTimeColumn2.ToString("dd.MM.yyyy").StartsWith(model.search.value));

return query.ToList() // here the error is thrown

我得到 NullReferenceException 错误

发生异常:CLR/System.NullReferenceException 异常 'System.NullReferenceException' 类型发生在 Microsoft.EntityFrameworkCore.dll 但未在用户代码中处理: '你调用的对象是空的。'在 System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor
1.EnumeratorExceptionInterceptor.MoveNext()

如果我注释掉第二列的行,它可以工作

//|| m.DateTimeColumn2.ToString("dd.MM.yyyy").StartsWith(model.search.value)

model.search.value 是字符串值,我正在尝试过滤所有列。 DateTimeColumn2 在数据库中是 DateTime 数据类型,但用户输入字符串,因此我将 DateTimeColumn2 转换为字符串并尝试过滤到用户值。任何想法,我做错了什么?

【问题讨论】:

  • 您是否确认model.search.value 中的任何内容都不是null
  • DateTimeColumn2 是必填项,日期类型为DateTime,因此每一行都有值。

标签: linq entity-framework-core entity-framework-core-2.1


【解决方案1】:

这里发生的是那个部分......

|| m.DateTimeColumn2.ToString("dd.MM.yyyy").StartsWith(model.search.value)

...无法转换为 SQL(不支持ToString("dd.MM.yyyy")),因此 EF-core 自动切换到客户端评估。

但是,现在整个 Where 子句在客户端进行评估,包括第一部分,

m.Column1.Contains(model.search.value)

现在这第一部分变得容易受到空引用异常的影响。有些实体的null 对应Column1

当您删除 DateTimeColumn2 谓词时,整个语句可以转换为 SQL 并由数据库进行评估。

【讨论】:

  • 有道理!谢谢你。有没有办法解决这个不受支持的.ToString() 方法?
  • EF-core 有这个功能DbFunction。我还没有尝试过,但您也许可以将函数映射到 SQL 日期时间格式化函数。
  • 我试过DbFunction,但错误是一样的。我将使用带有附加 DateTimeString 列的视图对象来解决这个问题。
  • @Muflix 如果目标数据库是 SqlServer。将[DbFunction("FORMAT", "")]public static string Format(DateTime value, string format) =&gt; value.ToString(format); 添加到上下文类并用YourDbContext.Format(m.DateTimeColumn2, "dd.MM.yyyy") 替换m.DateTimeColumn2.ToString("dd.MM.yyyy") 应该可以解决问题(正如格特建议的那样)
  • @IvanStoev 谢谢你我会试试的,不幸的是我正在使用不支持format 功能的sql server 2008 r2。我用我自己的标量函数尝试了它,它使用了convert 函数。
【解决方案2】:

您的 DateTimeColumn2 可能有 NULL 值,这对于 DateTime 列来说是很正常的。此外,您不应将其转换为字符串,而应将搜索值转换为日期时间。用户搜索“01”是否表示任何月份和年份的任何第一个日期?

query = query.Where(m => m.Column1.Contains(model.search.value)
        || !m.DateTimeColumn2.HasValue
        || m.DateTimeColumn2.ToString("dd.MM.yyyy").StartsWith(model.search.value));

return query.ToList()

【讨论】:

    【解决方案3】:

    如果您认为由于任何 DateTimeColumn2 值可能为空而引发异常,请检查非空性:

    query = query.Where(m => ...
        || (m.DateTimeColumn2 != null &&
            m.DateTimeColumn2.ToString("dd.MM.yyyy").StartsWith(model.search.value)));
    

    【讨论】:

    • DateTimeColumn2DateTime,它不是 nullable。确定我试过你的代码,但错误是一样的:/这很奇怪。
    • 会不会是模型或者搜索或者值是空的?
    猜你喜欢
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    相关资源
    最近更新 更多