执行计划在`exec sp_executesql`和普通`SELECT`中有所不同

时间:2016-02-01 23:55:52

标签: sql-server-2008 linq-to-sql sql-execution-plan

我创建了很长的Linq-to-SQL表达式。您可能知道内部Linq-to-SQL使用exec sp_executesql进行查询执行。当我在我的应用程序中运行它时 - 它以30秒的超时异常崩溃。

然后我将结果SQL从SQL Server Profiler复制到SQL Server Management Studio,将exec sp_executesql替换为普通SELECT并尝试调试它 - 它在4秒内执行。正如我看到它的执行计划更短更好。

然后我又回到了exec sp_executesql,我发现执行计划又糟糕了。有任何想法吗?有没有解决方法?

更新:先生,我找到了原因。 exec sp_executesql 缓存错误的计划,然后永远使用它。当我向查询添加OPTION (RECOMPILE)时,它会再次开始快速运行。但是我找不到如何将它添加到Linq-to-SQL查询中?

1 个答案:

答案 0 :(得分:0)

强迫创建一个肮脏的黑客,但它起作用至少......

public static class XQueryableExt
{
    public static IEnumerable<T> AsEnumerable<T>(
        this IQueryable<T> source,
        bool recompile)
    {
        if (!recompile)
            return source.AsEnumerable<T>();
        FieldInfo field =
            source.GetType().GetField(
                "context",
                BindingFlags.NonPublic | BindingFlags.Instance);
        if (field == null)
            throw new ApplicationException("'field' is null");
        DataContext dataContext = field.GetValue(source) as DataContext;
        if (dataContext == null)
            throw new ApplicationException("'dataContext' is null");
        if (dataContext.Connection.State == ConnectionState.Closed)
            dataContext.Connection.Open();
        using (DbCommand command = dataContext.GetCommand(source)) {
            command.CommandText += " OPTION (RECOMPILE)";
            using (DbDataReader dataReader = command.ExecuteReader(CommandBehavior.CloseConnection)) {
                return dataContext.Translate<T>(dataReader).ToArray();
            }
        }
    }
}