【问题标题】:Entity Framework 6 ToString(), formatting (DateTime format), query interceptEntity Framework 6 ToString(),格式化(DateTime格式),查询拦截
【发布时间】:2014-09-30 13:39:16
【问题描述】:

我没有找到在 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

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

【问题讨论】:

    标签: entity-framework linq-to-sql mapping


    【解决方案1】:

    为什么不直接使用 Year 和 Month 属性?您应该能够将字符串输入转换为年份和月份数字。然后你做这样的事情:

    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”等。我需要在日期时间字段中搜索。
    • @AlexandrSulimov,我更新了我的答案。它应该产生你想要的格式。你可以使用它,以防万一你想阻止使用拦截器,因为它是全局应用的。
    • 有问题。用户过滤器是“12.12”its may be "2012.12.01" or may be "2010.12.12". Or user filter is "12" its 任何数据时间的任何 12。
    • 嗯,应该可以,我尝试使用您的示例 2012.12.012012.12.12,过滤器是 12.1212,并且两个日期时间都匹配两个过滤器,因为在那些将被转换为2012.12.012012.12.12Contains 的数据库将进行字符串过滤
    • 谢谢,你的方法很好。但是我不能用 Expression (stackoverflow.com/questions/25290720/…) 来创建这个查询
    【解决方案2】:
    1. 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 ());
        }
    }
    

    【讨论】:

    • 它作为学习样本很好,但不推荐:用 dbo.ToString( 替换每个 CAST( - 由于 EF 使用 CAST( 也主动...
    猜你喜欢
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    • 2010-10-22
    • 2010-12-22
    相关资源
    最近更新 更多