仅将 IDbInterceptor 挂接到 EntityFramework DbContext 一次
Hooking IDbInterceptor to EntityFramework DbContext only once
IDbCommandInterceptor
接口没有很好的文档记录。而且我只找到了一些关于它的稀缺教程:
- http://www.entityframeworktutorial.net/entityframework6/database-command-interception.aspx
- https://msdn.microsoft.com/en-us/data/jj556606%28v=vs.113%29.aspx
- https://entityframework.codeplex.com/wikipage?title=Interception
- https://www.tutorialspoint.com/entity_framework/entity_framework_command_interception.htm
- https://msdn.microsoft.com/en-us/data/dn469464%28v=vs.113%29.aspx
还有一些 SO 问题:
- Entity Framework 6 - Timing queries
- Getting DbContext from implementation of IDbCommandInterceptor
这些是我发现的关于挂钩的建议:
1 - 静态 DbInterception
class:
DbInterception.Add(new MyCommandInterceptor());
2 - 在 DbConfiguration
class
中执行上述建议
public class MyDBConfiguration : DbConfiguration {
public MyDBConfiguration() {
DbInterception.Add(new MyCommandInterceptor());
}
}
3 - 使用配置文件:
<entityFramework>
<interceptors>
<interceptor type="EFInterceptDemo.MyCommandInterceptor, EFInterceptDemo"/>
</interceptors>
</entityFramework>
尽管我不知道如何将 DbConfiguration
class 挂接到 DbContext,也不知道在配置方法的 type
部分中放置什么。 Another example I found 似乎建议你写一个记录器的命名空间:
type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework"
我注意到 DataBaseLogger
实现了 IDisposable
、IDbConfigurationInterceptor
和
IDbInterceptor
。 IDbCommandInterceptor
也实现了 IDbInterceptor
,所以我尝试(但没有成功)将其格式化为:
type="DataLayer.Logging.MyCommandInterceptor, DataLayer"
而当我直接调用静态 DbInterception
class 时,它每次调用都会添加另一个拦截器。所以我快速而肮脏的解决方案是利用静态构造函数:
//This partial class is a seperate file from the Entity Framework auto-generated class,
//to allow dynamic connection strings
public partial class MyDbContext // : DbContext
{
public Guid RequestGUID { get; private set; }
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
DbContextListeningInitializer.EnsureListenersAdded();
RequestGUID = Guid.NewGuid();
//Database.Log = m => System.Diagnostics.Debug.Write(m);
}
private static class DbContextListeningInitializer
{
static DbContextListeningInitializer() //Threadsafe
{
DbInterception.Add(new MyCommandInterceptor());
}
//When this method is called, the static ctor is called the first time only
internal static void EnsureListenersAdded() { }
}
}
但是 proper/intended 方法是什么?
我发现我的 DbContext
class 只需要具有 DbConfigurationType
属性,以便在运行时附加配置:
[DbConfigurationType(typeof(MyDBConfiguration))]
public partial class MyDbContext // : DbContext
{
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{ }
}
public class MyDBConfiguration : DbConfiguration {
public MyDBConfiguration() {
this.AddInterceptor(new MyCommandInterceptor());
}
}
docs建议直接放在Application_Start
:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DbInterception.Add(new SchoolInterceptorTransientErrors());
DbInterception.Add(new SchoolInterceptorLogging());
}
重要的是它只被调用一次。
IDbCommandInterceptor
接口没有很好的文档记录。而且我只找到了一些关于它的稀缺教程:
- http://www.entityframeworktutorial.net/entityframework6/database-command-interception.aspx
- https://msdn.microsoft.com/en-us/data/jj556606%28v=vs.113%29.aspx
- https://entityframework.codeplex.com/wikipage?title=Interception
- https://www.tutorialspoint.com/entity_framework/entity_framework_command_interception.htm
- https://msdn.microsoft.com/en-us/data/dn469464%28v=vs.113%29.aspx
还有一些 SO 问题:
- Entity Framework 6 - Timing queries
- Getting DbContext from implementation of IDbCommandInterceptor
这些是我发现的关于挂钩的建议:
1 - 静态 DbInterception
class:
DbInterception.Add(new MyCommandInterceptor());
2 - 在 DbConfiguration
class
public class MyDBConfiguration : DbConfiguration {
public MyDBConfiguration() {
DbInterception.Add(new MyCommandInterceptor());
}
}
3 - 使用配置文件:
<entityFramework>
<interceptors>
<interceptor type="EFInterceptDemo.MyCommandInterceptor, EFInterceptDemo"/>
</interceptors>
</entityFramework>
尽管我不知道如何将 DbConfiguration
class 挂接到 DbContext,也不知道在配置方法的 type
部分中放置什么。 Another example I found 似乎建议你写一个记录器的命名空间:
type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework"
我注意到 DataBaseLogger
实现了 IDisposable
、IDbConfigurationInterceptor
和
IDbInterceptor
。 IDbCommandInterceptor
也实现了 IDbInterceptor
,所以我尝试(但没有成功)将其格式化为:
type="DataLayer.Logging.MyCommandInterceptor, DataLayer"
而当我直接调用静态 DbInterception
class 时,它每次调用都会添加另一个拦截器。所以我快速而肮脏的解决方案是利用静态构造函数:
//This partial class is a seperate file from the Entity Framework auto-generated class,
//to allow dynamic connection strings
public partial class MyDbContext // : DbContext
{
public Guid RequestGUID { get; private set; }
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
DbContextListeningInitializer.EnsureListenersAdded();
RequestGUID = Guid.NewGuid();
//Database.Log = m => System.Diagnostics.Debug.Write(m);
}
private static class DbContextListeningInitializer
{
static DbContextListeningInitializer() //Threadsafe
{
DbInterception.Add(new MyCommandInterceptor());
}
//When this method is called, the static ctor is called the first time only
internal static void EnsureListenersAdded() { }
}
}
但是 proper/intended 方法是什么?
我发现我的 DbContext
class 只需要具有 DbConfigurationType
属性,以便在运行时附加配置:
[DbConfigurationType(typeof(MyDBConfiguration))]
public partial class MyDbContext // : DbContext
{
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{ }
}
public class MyDBConfiguration : DbConfiguration {
public MyDBConfiguration() {
this.AddInterceptor(new MyCommandInterceptor());
}
}
docs建议直接放在Application_Start
:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DbInterception.Add(new SchoolInterceptorTransientErrors());
DbInterception.Add(new SchoolInterceptorLogging());
}
重要的是它只被调用一次。