仅将IDbInterceptor挂钩到EntityFramework DbContext一次
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
还有一些问题:
- entity framework6 – 定时查询
- 从IDbCommandInterceptor的实现中获取DbContext
这些是我发现的挂钩建议:
1 – 静态DbInterception
类:
DbInterception.Add(new MyCommandInterceptor());
2 – 在DbConfiguration
类中执行上述建议
public class MyDBConfiguration : DbConfiguration { public MyDBConfiguration() { DbInterception.Add(new MyCommandInterceptor()); } }
3 – 使用配置文件:
虽然我无法弄清楚如何将DbConfiguration
类挂钩到DbContext,也不知道如何将配置方法的type
部分放入。 我发现的另一个例子似乎建议您编写记录器的命名空间:
type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework"
我注意到DataBaseLogger
实现了IDisposable
, IDbConfigurationInterceptor
和
IDbInterceptor
。 IDbCommandInterceptor
也实现了IDbInterceptor
,所以我尝试(没有成功)将其格式化为:
type="DataLayer.Logging.MyCommandInterceptor, DataLayer"
当我直接调用静态DbInterception
类时,它在每次调用时都添加了另一个拦截器。 所以我的快速而肮脏的解决方案是利用静态构造函数:
//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() { } } }
但是,正确/有意的方法是什么?
我发现我的DbContext
类只需要具有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()); } }
文档建议你可以把它放在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()); }
重要的是它只被召唤一次。