我遇到了这个:
https://entityframework.codeplex.com/wikipage?title=拦截
看来您可以执行以下操作:
public class HintInterceptor : DbCommandInterceptor
{
public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
command.CommandText += " option (recompile)";
base.ReaderExecuting(command, interceptionContext);
}
}
并像这样注册它(我在Application_Start
of 中做到了global.asax.cs
):
DbInterception.Add(new HintInterceptor());
它会让你改变CommandText
. 唯一的问题是它现在附加到每个读者查询中,这可能是一个问题,因为其中一些可能会受到该提示的负面影响。我猜我可以根据上下文做一些事情来确定提示是否合适,或者更糟糕的情况我可以检查它CommandText
本身。
似乎不是最优雅或最细粒度的解决方案。
编辑:从interceptorContext
,你可以得到DbContexts
,所以我定义了一个如下所示的接口:
public interface IQueryHintContext
{
string QueryHint { get; set; }
bool ApplyHint { get; set; }
}
然后创建了一个派生自我原来的 DbContext(由 EF 生成)并实现上述接口的类。然后我将拦截器更改为如下所示:
public class HintInterceptor : DbCommandInterceptor
{
public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
{
if (interceptionContext.DbContexts.Any(db => db is Dal.IQueryHintContext))
{
var ctx = interceptionContext.DbContexts.First(db => db is Dal.IQueryHintContext) as Dal.IQueryHintContext;
if (ctx.ApplyHint)
{
command.CommandText += string.Format(" option ({0})", ctx.QueryHint);
}
}
base.ReaderExecuting(command, interceptionContext);
}
}
现在要使用它,我使用派生类而不是原始类创建一个上下文,设置QueryHint
为我想要的任何内容(recompile
在本例中)并ApplyHint
在我执行命令之前设置,然后将其设置回 false。
为了让这一切更加独立,我最终定义了一个这样的接口:
public interface IQueryHintContext
{
string QueryHint { get; set; }
bool ApplyHint { get; set; }
}
并像这样扩展了我的数据库上下文(当然,您也可以使用部分类来扩展 EF 生成的类):
public class MyEntities_Ext : MyEntities, IQueryHintContext
{
public string QueryHint { get; set; }
public bool ApplyHint { get; set; }
}
然后,为了使开启、关闭部分更容易处理,我定义了这个:
public class HintScope : IDisposable
{
public IQueryHintContext Context { get; private set; }
public void Dispose()
{
Context.ApplyHint = false;
}
public HintScope(IQueryHintContext context, string hint)
{
Context = context;
Context.ApplyHint = true;
Context.QueryHint = hint;
}
}
现在要使用它,我可以这样做:
using (var ctx = new MyEntities_Ext())
{
// any code that didn't need the query hint
// ....
// Now we want the query hint
using (var qh = new HintScope(ctx, "recompile"))
{
// query that needs the recompile hint
}
// back to non-hint code
}
这可能有点矫枉过正并且可以进一步开发(例如,使用枚举而不是字符串来获取可用提示 - 或子类化recompile
查询提示,这样您就不需要recompile
每次都指定字符串并冒着打字错误的风险),但它解决了我的直接问题。