我有一个动态查询,它太大而无法放在这里。可以肯定地说,在当前形式中,它利用 CLR 过程根据传递的搜索参数的数量动态构建连接,然后获取该结果并将其连接到更详细的表,以带回对最终用户重要的属性。我已将整个查询转换为 LINQ to Entities,我发现它生成的 SQL 足够高效来完成这项工作,但是通过 EF 6 运行时,查询超时。获取生成的 SQL 并在 SSMS 中运行它只需 3 秒或更短的时间。我只能想象我的问题是参数嗅探。我已经尝试更新数据库中每个表的统计信息,但这并没有解决问题。
我的问题是:
我能否以某种方式通过 EF 嵌入诸如“OPTION RECOMPILE”之类的选项?
最佳答案
可以使用 EF6 的拦截功能在 DB 上执行之前操作其内部 SQL 命令,例如在命令末尾添加 option(recompile)
:
public class OptionRecompileHintDbCommandInterceptor : IDbCommandInterceptor
{
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<Int32> interceptionContext)
{
}
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
addQueryHint(command);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
addQueryHint(command);
}
private static void addQueryHint(IDbCommand command)
{
if (command.CommandType != CommandType.Text || !(command is SqlCommand))
return;
if (command.CommandText.StartsWith("select", StringComparison.OrdinalIgnoreCase) && !command.CommandText.Contains("option(recompile)"))
{
command.CommandText = command.CommandText + " option(recompile)";
}
}
}
要使用它,请在应用程序的开头添加以下行:
DbInterception.Add(new OptionRecompileHintDbCommandInterceptor());
关于c# - EF 6 参数嗅探,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25145667/