首页 > 解决方案 > 通过 IDbCommandInterceptor 检测或传递 Entity Framework 6 和 Entity Framework Core 中的调用方法

问题描述

我有兴趣捕获启动实体框架查询的方法的名称。我将在 Entity Framework 6 和 Entity Framework Core 中使用此功能

考虑以下类:

命名空间 MyCompany.MyApp
{
    公共类 MyDataClass
    {
        // ... 剪断 ...
        
        public Person GetPerson(long id)
        {
            返回 _dbContext
                。人
                .FirstOrDefault(p => p.Id == id);
        }
    }
}

以及以下拦截器:

public class EFCommandInterceptor : IDbCommandInterceptor
{
    // ... snip other interface methods ...

    public void ReaderExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
    {
        var callingMehtod = GetCallingMethod() // <--- I'd like this to return the string "MyCompany.MyApp.MyDataClass.GetPerson"
    }
}

有什么方法可以确定是什么方法启动了导致调用拦截器的查询?

由于我将使用此功能进行跟踪和性能分析,因此我无法发送和记录Environment.StackTrace通过系统运行的每个查询的全部内容。

我还考虑StackTrace过结合使用该类stackTrace.GetFrames()来尝试分析调用堆栈以找到启动查询的实际方法,但目前尚不清楚如何在不依赖某种通用标识数据访问类的命名空间约定的情况下可靠地执行此操作.

另一种可以接受的方法可能类似于:

命名空间 MyCompany.MyApp
{
    公共类 MyDataClass
    {
        // ... 剪断 ...
        
        public Person GetPerson(long id)
        {
            返回 _dbContext
                。人
                .WithExtraInterceptorContext(new { CallingMethod = "MyCompany.MyApp.MyDataClass.GetPerson"}) // <--- 可以这样做吗?
                .FirstOrDefault(p => p.Id == id);
        }
    }
}

上面示例的意图是稍后能够通过DbCommandInterceptionContext内部检索额外的上下文IDbCommandInterceptor

最终,我要解决的问题是在没有完整调用堆栈的情况下获取启动查询的方法的完全限定名称。

标签: c#entity-frameworkentity-framework-core

解决方案


使用 EF Core,您可以使用 TagWith

var result = db.Albums
               .TagWith(MethodBase.GetCurrentMethod().Name)
               .ToList();

推荐阅读