Entity Framework 6 ToString(),格式化(DateTime格式),查询拦截

4

我找不到在DateTime(DateTime?)字段中使用linq2sql进行搜索的正确方法。

db.Items.Where(x => x.DateTime1.ToString().Contains("2014.08"))

无法工作,因为在linq2sql中创建CAST([XXXX.DateTime1] AS NVARCHAR(MAX)) = '04 Aug 2014' NOT 2014.08

我尝试使用自定义函数映射,但没有结果。

2个回答

4
为什么不直接使用“年份”和“月份”属性呢?您应该能够将字符串输入转换为年份和月份数字。然后,您可以执行以下操作:
db.Items.Where(x => 
   x.DateTime1.Value.Year == 2014 
   && x.DateTime1.Value.Month == 8)

它将简单地转换为:
WHERE (2014 = (DATEPART (year, [Extent1].[Date]))) 
AND     (8 = (DATEPART (month, [Extent1].[Date])))

更新

您可以使用SqlFunctions.DatePartDbFunctions.Right来生成以下格式的日期 yyyy.mm.dd

db.Items.Where(x => 
    (SqlFunctions.DatePart("yyyy", x.DateTime) + "."
    + DbFunctions.Right("0" + SqlFunctions.DatePart("m", x.DateTime1), 2) + "."
    + DbFunctions.Right("0" + SqlFunctions.DatePart("d", x.DateTime1), 2))
    .Contains("2014.08"));

用户输入字符串"2014.08"、"08.08"或"14.08"等,我需要在日期时间字段中进行搜索。 - Alexandr Sulimov
@AlexandrSulimov,我更新了我的答案。它应该可以生成你想要的格式。如果你想避免使用拦截器,因为它是全局应用的,你可以使用这个。 - Yuliam Chandra
有一个问题。用户筛选器是“12.12”,它可能是“2012.12.01”或“2010.12.12”。或者用户筛选器是“12”,它可以匹配任何日期时间中的12。 - Alexandr Sulimov
嗯,那应该可以工作。我尝试了你的示例 2012.12.012012.12.12,过滤器是 12.1212,两个日期时间都匹配这两个过滤器,因为在数据库中它们将被转换为 2012.12.012012.12.12,而 Contains 将执行字符串过滤。 - Yuliam Chandra
谢谢,你的方法很好。但我无法使用表达式创建这个查询(http://stackoverflow.com/questions/25290720/conversion-in-linq-and-entityframework-expressions-type-without-expression-conv)。 - Alexandr Sulimov
@AlexandrSulimov,DatePart接受可空参数,而可空参数可以接受非可空参数。 - Yuliam Chandra

0
MS SQL 中的函数
CREATE FUNCTION [dbo].[ToString](@P sql_variant)
RETURNS NVARCHAR(20)
AS
BEGIN
    IF (sql_variant_property(@P, 'BaseType') = 'datetime')
        RETURN CONVERT(NVARCHAR(10), @P, 102) + ' ' + CONVERT(NVARCHAR(8), @P, 108);

RETURN CAST(@P as NVARCHAR(max));
END
  1. 创建 SQL 执行拦截器
public class DbCommandInterceptor  : IDbCommandInterceptor 
{
    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        if (command.CommandText.IndexOf("CAST") != -1)
        {
            command.CommandText = command.CommandText.Replace("CAST(", "dbo.ToString(");
            command.CommandText = command.CommandText.Replace("] AS nvarchar(max))", "])");

        }
    }

}

  1. 在DbContext中添加拦截器
public class DB : DbContext
{
    public DB(): base(@"Data Source=localhost\SQLEXPRESS;Initial Catalog=EFTest")
    {
        DbInterception.Add(new DbCommandInterceptor ());
    }
}

这是一个很好的学习样本,但不能推荐使用:将每个CAST(替换为dbo.ToString() - 通常不起作用,因为EF会自行使用CAST()。 - Roman Pokrovskij

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接