将调试信息注入实体框架查询

时间:2014-02-06 14:53:58

标签: c# sql sql-server entity-framework instrumentation

我们在我们的商店中使用Dapper和EF,并且当出现问题时,Dapper证明在SQL服务器中调试查询非常有用。我们创建了一个瘦装饰器,而不仅仅是提交原始SQL,它还添加了一些上下文信息(原点)作为SQL注释,类似于

/* Foo.Bar.GetOrders() */ SELECT * FROM Order WHERE orderId > 123

这使得我们的DBA和开发人员可以非常快速地进行查找,如果我们有错误的数据库调用,或者引入性能命中(我们每天有数十万个数据库调用,那么一个错误的查询可以造成相当大的伤害。)

我们也希望用EF做到这一点。它不一定是SQL注释,而是某种钩子,以便提供随调用一起提交的元信息。不知道这是否可行?

感谢您的建议

菲利普

2 个答案:

答案 0 :(得分:4)

事实证明,使用EF 6变得非常容易。所有需要的是 IDbCommandInterceptor 的实现,它允许我使用自定义(SQL)注释来扩充提交的SQL。该注释将出现在数据库日志中,从而启用DBA端的调试/跟踪。

public class DebugCommentInterceptor : IDbCommandInterceptor
{
    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        command.CommandText = "/* TRACING INFORMATION GOES HERE */ " + command.CommandText;
    }

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        command.CommandText = "/* TRACING INFORMATION GOES HERE */ " + command.CommandText;
    }

    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }

    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
    }

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

    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }
}

为了使上述拦截器可操作,我只是使用静态 DbInterception 类注册它:

DbInterception.Add(new DebugCommentInterceptor());

答案 1 :(得分:1)

如果使用EF Core,则可以使用查询标签。

[0, class<'TopoDS_Shape'; Type:Compound; id:1813291361>]
[0, class<'TopoDS_Shape'; Type:Compound; id:1813291361>]
[0, class<'TopoDS_Shape'; Type:Compound; id:1813291361>]
[0, class<'TopoDS_Shape'; Type:Compound; id:1813291361>]
[0, class<'TopoDS_Shape'; Type:Compound; id:1813291361>]
[0, class<'TopoDS_Shape'; Type:Compound; id:1813291361>]
[0, class<'TopoDS_Shape'; Type:Compound; id:1813291361>]
[7, class<'TopoDS_Shape'; Type:Compound; id:1812116593>]
[7, class<'TopoDS_Shape'; Type:Compound; id:1812116593>]
[7, class<'TopoDS_Shape'; Type:Compound; id:1812116593>]
[7, class<'TopoDS_Shape'; Type:Compound; id:1812116593>]
[7, class<'TopoDS_Shape'; Type:Compound; id:1812116593>]
[7, class<'TopoDS_Shape'; Type:Compound; id:1812116593>]
[7, class<'TopoDS_Shape'; Type:Compound; id:1812116593>]
[14, class<'TopoDS_Shape'; Type:Compound; id:1812470737>]
[14, class<'TopoDS_Shape'; Type:Compound; id:1812470737>]
[14, class<'TopoDS_Shape'; Type:Compound; id:1812470737>]
[14, class<'TopoDS_Shape'; Type:Compound; id:1812470737>]
[14, class<'TopoDS_Shape'; Type:Compound; id:1812470737>]
[14, class<'TopoDS_Shape'; Type:Compound; id:1812470737>]
[14, class<'TopoDS_Shape'; Type:Compound; id:1812470737>]

有一个新的linq var nearestFriends = (from f in context.Friends.TagWith("This is my spatial query!") orderby f.Location.Distance(myLocation) descending select f).Take(5).ToList(); ,它将使用以下命令生成Sql查询:

.TagWith('')

https://docs.microsoft.com/en-us/ef/core/querying/tags