在旧的(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月)?
答案 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.html和https://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中的工作方式相同