提问者:小点点

通过IDbCommandInterceptor检测或传递实体框架6和实体框架核心中的调用方法


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

请考虑以下类:

namespace MyCompany.MyApp
{
    public class MyDataClass
    {
        // ... snip ...
        
        public Person GetPerson(long id)
        {
            return _dbContext
                .Person
                .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"
    }
}

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

由于我将使用此功能进行跟踪和性能分析,因此我无法为通过系统运行的每个查询发送和记录整个环境.stacktrace

我还考虑将StackTrace类与StackTrace.getFrames()结合使用,以尝试分析调用堆栈,从而找到启动查询的实际方法,但不清楚如何在不依赖于某种通用标识数据访问类的命名空间约定的情况下可靠地完成此操作。

另一种可以接受的方法可能是:

namespace MyCompany.MyApp
{
    public class MyDataClass
    {
        // ... snip ...
        
        public Person GetPerson(long id)
        {
            return _dbContext
                .Person
                .WithExtraInterceptorContext(new { CallingMethod = "MyCompany.MyApp.MyDataClass.GetPerson"}) // <--- Can something like this be done?
                .FirstOrDefault(p => p.Id == id);
        }
    }
}

以上示例的意图是以后能够通过IDBCommandInterceptor内部的DBCommandInterceptionContext检索额外的上下文

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


共2个答案

匿名用户

您可以在运行查询之前简单地注册信息,如下所示:

    public Person GetPerson(long id)
    {
        EfDebug.SetCurrentMethodName();
        return _dbContext
            .Person
            .WithExtraInterceptorContext(new { CallingMethod = "MyCompany.MyApp.MyDataClass.GetPerson"}) // <--- Can something like this be done?
            .FirstOrDefault(p => p.Id == id);
    }

。。。

class EfDebug
{
  static string CurrentMethodName {get;set;}
  public void SetCurrentMethodName( [CallerMemberName] string caller = "" )
  {
     CurrentMethodName = caller;
  }
}

匿名用户

对于EF Core,您可以使用TagWith