我喜欢 VahidN 的解决方案,给他投票,但我想要更多地控制何时它发生。事实证明,DB 拦截器是非常全球化的,我只希望这发生在特定场景的特定上下文中。
在这里,我们正在设置基础工作以支持添加其他查询提示,这些提示可以根据需要打开和关闭。
由于我经常公开传递连接字符串的方法,所以我也包括了对它的支持。
下面将为您的上下文提供一个标志,以通过扩展 EF 生成的部分类以编程方式启用/禁用提示。我们还将 Interceptor 中的一小段重用代码扔到了它自己的方法中。
小界面
public interface IQueryHintable
{
bool HintWithRecompile { get; set; }
}
数据库命令拦截器
public class OptionHintDbCommandInterceptor : IDbCommandInterceptor
{
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<Int32> interceptionContext)
{
AddHints(command, 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)
{
AddHints(command, interceptionContext);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
AddHints(command, interceptionContext);
}
private static void AddHints<T>(DbCommand command, DbCommandInterceptionContext<T> interceptionContext)
{
var context = interceptionContext.DbContexts.FirstOrDefault();
if (context is IQueryHintable)
{
var hints = (IQueryHintable)context;
if (hints.HintWithRecompile)
{
addRecompileQueryHint(command);
}
}
}
private static void addRecompileQueryHint(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)";
}
}
}
扩展实体上下文以添加 IQueryHintable
public partial class SomeEntities : DbContext, IQueryHintable
{
public bool HintWithRecompile { get; set; }
public SomeEntities (string connectionString, bool hintWithRecompile) : base(connectionString)
{
HintWithRecompile = hintWithRecompile;
}
public SomeEntities (bool hintWithRecompile) : base()
{
HintWithRecompile = hintWithRecompile;
}
public SomeEntities (string connectionString) : base(connectionString)
{
}
}
注册数据库命令拦截器 (global.asax)
DbInterception.Add(new OptionHintDbCommandInterceptor());
启用上下文范围
using(var db = new SomeEntities(hintWithRecompile: true) )
{
}
开启或关闭
db.HintWithRecompile = true;
// Do Something
db.HintWithRecompile = false;
我将此称为 HintWithRecompile,因为您可能还想实现 HintOptimizeForUnknown 或其他查询提示。