我可以在EntityFramework Core中配置拦截器吗?

时间:2016-06-06 15:02:54

标签: c# visual-studio-2015 entity-framework-core

在旧的(pre-core)时代的实体框架6中,如此blog post所示,有一种方法可以配置一个拦截器,它可以记录所有慢速查询,包括堆栈回溯。

[注意:在Entity Framework Core 1.0 RC2中,当我被问到时,我相信这是不可能的。这个问题最初问的是做什么。自提出此问题以来,EF COre的新选项和新版本已经发布。这个问题本质上是历史性的,后来添加的一些答案引用了其他较新版本的EF Core,其中可能已经重新引入了拦截器,以实现与核心时代前实体框架的特征奇偶性]

2015年的一个问题是关于之前称为EF7的测试版的早期测试结果,表明它在早期版本的asp.net vnext中不是possible yet

然而,EF Core的整个设计是可组合的,并且在讨论github bug跟踪器here时,可能有一种技术可以将一些低级类子类化为SqlServerConnection,然后覆盖其中有一些方法,可以在执行查询之前和之后获取一些可以挂钩的点,如果执行了毫秒计时器值,则添加一些低级别的日志记录。

这仍然是必要的,也是EF Core 1.0.0-rc2-final中唯一的技术(目前截至2016年6月)?

3 个答案:

答案 0 :(得分:6)

EF Core还没有“拦截器”或类似的生命周期钩子。此功能在此处进行跟踪:https://github.com/aspnet/EntityFramework/issues/626

如果您想要的只是日志输出,则可能不需要覆盖低级组件。许多低级EF Core组件已经生成日志记录,包括查询执行的日志记录。您可以通过调用[routerLink]="['../ProjectDetail', {slug: projekt.slug }]" 将EF配置为使用自定义记录器工厂。 (有关此记录器接口的更多详细信息,请参阅https://docs.asp.net/en/latest/fundamentals/logging.htmlhttps://github.com/aspnet/Logging。)EF Core会生成一些具有良好定义的事件ID的值得注意的日志事件。 (请参阅1.0.0-rc2中的DbContextOptionsBuilder.UseLoggerFactory(ILoggerFactory factory),其中1.0.0 RTM已重命名为Microsoft.EntityFrameworkCore.Infrastructure.CoreLoggingEventId。)有关此操作的示例,请参阅https://docs.efproject.net/en/latest/miscellaneous/logging.html

如果您需要超出EF Core组件已经生成的额外日志记录,则需要覆盖EF Core的低级组件。最好通过覆盖现有组件并通过依赖注入将此重写版本添加到EF来完成。这样做需要为EF配置自定义服务提供程序以在内部使用。这是由Microsoft.EntityFrameworkCore.Infrastructure.CoreEventId配置的。有关EF如何在内部使用服务的更多详细信息,请参阅https://docs.efproject.net/en/latest/miscellaneous/internals/services.html

答案 1 :(得分:1)

以下是ajcvickers在github上找到的有关如何在EF CORE中使用拦截器的示例(在回答此问题时为2.2):

public class NoLockInterceptor : IObserver<KeyValuePair<string, object>>
{
    public void OnCompleted()
    {
    }

    public void OnError(Exception error)
    {
    }

    public void OnNext(KeyValuePair<string, object> value)
    {
        if (value.Key == RelationalEventId.CommandExecuting.Name)
        {
            var command = ((CommandEventData)value.Value).Command;

            // Do command.CommandText manipulation here
        }
    }
}

接下来,为EF诊断创建一个全局侦听器。像这样:

public class EfGlobalListener : IObserver<DiagnosticListener>
{
    private readonly NoLockInterceptor _noLockInterceptor = new NoLockInterceptor();

    public void OnCompleted()
    {
    }

    public void OnError(Exception error)
    {
    }

    public void OnNext(DiagnosticListener listener)
    {
        if (listener.Name == DbLoggerCategory.Name)
        {
            listener.Subscribe(_noLockInterceptor);
        }
    }
}

并将其注册为应用程序启动的一部分:

DiagnosticListener.AllListeners.Subscribe(new EfGlobalListener());

答案 2 :(得分:0)

EntityFramework Core 3.0即将推出:https://github.com/aspnet/EntityFrameworkCore/issues/15066

它的工作方式与EF 6中的工作方式相同