实体框架生成datetime2参数以与日期列进行比较 - 如何匹配列的数据类型

时间:2015-07-24 16:45:39

标签: entity-framework entity-framework-6

是否有强制实体框架发送date参数以匹配列数据类型?这导致我们的一些查询中的密钥查找非常昂贵。

示例生成的查询在几分钟内运行,我从SQL Server探查器中抓取:

exec sp_executesql N'SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [table] AS [Extent1]
        WHERE ( EXISTS (SELECT 
            1 AS [C1]
            FROM [search] AS [Extent2]
            WHERE ([Extent1].[Number] = [Extent2].[Number]) AND ([Extent2].[SearchInstance] = @p__linq__0)
        )) AND ([Extent1].[Date] >= @p__linq__1) AND ([Extent1].[Date] <= @p__linq__2)
    )  AS [GroupBy1]',N'@p__linq__0 uniqueidentifier,@p__linq__1 datetime2(7),@p__linq__2 datetime2(7)',@p__linq__0='1A530478-17F8-442E-B718-32049086717F',@p__linq__1='2012-07-24',@p__linq__2='2015-07-24'

如果我手动更改日期参数的类型,则此查询将在0秒内执行。

exec sp_executesql N'SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM [table] AS [Extent1]
        WHERE ( EXISTS (SELECT 
            1 AS [C1]
            FROM [search] AS [Extent2]
            WHERE ([Extent1].[Number] = [Extent2].[Number]) AND ([Extent2].[SearchInstance] = @p__linq__0)
        )) AND ([Extent1].[Date] >= @p__linq__1) AND ([Extent1].[Date] <= @p__linq__2)
    )  AS [GroupBy1]',N'@p__linq__0 uniqueidentifier,@p__linq__1 date,@p__linq__2 date',@p__linq__0='1A530478-17F8-442E-B718-32049086717F',@p__linq__1='2012-07-24',@p__linq__2='2015-07-24'

使用ef codefirst,我指定.HasColumType("date")但未更改正在发送的参数类型。

**表名和表格列已被更改以保护无辜。

1 个答案:

答案 0 :(得分:1)

粗略地说,使用DbInterceptor。

using System.Data;
using System.Data.Common;
using System.Data.Entity.Infrastructure.Interception;
using System.Data.SqlClient;
using System.Linq;

public static class SomewhereDoThis 
{
    public static void Register() 
    {
        DbInterception.Add(new DateInterceptor());
    }
}

public class DateInterceptor : IDbCommandInterceptor
{
    /* .. */

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        ShrinkDates(command);
    }
    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        ShrinkDates(command);
    }

    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext interceptionContext)
    {
        ShrinkDates(command);
    }

    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
        ShrinkDates(command);
    }

    private static void ShrinkDates(DbCommand command)
    {
        command.Parameters
            .OfType<SqlParameter>()
            .Where(p => p.SqlDbType == SqlDbType.DateTime2)
            .Where(p => p.Value != DBNull.Value)
            .Where(p => p.Value is DateTime)
            .Where(p => ((DateTime)p.Value).TimeOfDay == TimeSpan.Zero)
            .ToList()
            .ForEach(p => p.SqlDbType = SqlDbType.Date);
    }
}