Entity Framework Extensions Connection Interception
The DbConnectionInterceptor
is a class that can receive notifications when Entity Framework uses a connection. You must override the method from this class.
To get this feature in your EF Core, install the Z.EntityFramework.Extensions.EFCore NuGet package or run the following command in Package Manager Console.
PM> Install-Package Z.EntityFramework.Extensions.EFCore
Create Interceptor
To implement connection interception, we need to create a custom interceptor and register it accordingly. Entity Framework will call it whenever a connection is used.
Let's create a new class EFConnectionInterceptor
that implements DbConnectionInterceptor
class which is available in Z.EntityFramework.Extensions.EFCore.
public class EFConnectionInterceptor : DbConnectionInterceptor { public override void Opening(DbConnection connection, DbConnectionInterceptionContext interceptionContext) { base.Opening(connection, interceptionContext); LogInfo("EFConnectionInterceptor.Opening", interceptionContext.EventData.ToString()); } public override void Opened(DbConnection connection, DbConnectionInterceptionContext interceptionContext) { base.Opened(connection, interceptionContext); LogInfo("EFConnectionInterceptor.Opened", interceptionContext.EventData.ToString()); } public override void Error(DbConnection connection, DbConnectionInterceptionContext interceptionContext, Exception exception) { base.Error(connection, interceptionContext, exception); LogInfo("EFConnectionInterceptor.Error", interceptionContext.EventData.ToString(), exception.Message); } public override void Closing(DbConnection connection, DbConnectionInterceptionContext interceptionContext) { base.Closing(connection, interceptionContext); LogInfo("EFConnectionInterceptor.Closing", interceptionContext.EventData.ToString()); } public override void Closed(DbConnection connection, DbConnectionInterceptionContext interceptionContext) { base.Closed(connection, interceptionContext); LogInfo("EFConnectionInterceptor.Closed", interceptionContext.EventData.ToString()); } private void LogInfo(string method, string data) { Console.WriteLine("Intercepted on: {0}: \n\t{1}", method, data); } private void LogInfo(string method, string data, string exception) { Console.WriteLine("Intercepted on: {0}: \n\t{1} \n\t{2}", method, data, exception); } }
This code writes connection information on the Console Window. The DbConnectionInterceptionContext
currently have the following properties:
- DbContext
- EventData which contains all information about this event.
Register Interceptor
Once a class that implements the interception has been created it can be registered using the DbInterception
class as shown below.
DbInterception.Add(new EFConnectionInterceptor());
You can add interceptors using the DbInterception.Add
method anywhere in your code such as, Application_Start
method or in the DbConfiguration
class, etc.
- Be careful not to execute
DbInterception.Add
for the same interceptor more than once, otherwise, you will get additional interceptor instances. - For example, if you add the logging interceptor twice, you will see two logs for every SQL query.
- In this example, we will register the interceptor in the
main
method.
You can also bind the interceptor to the context if you want to have information about context, but this step is optional.
public static EFConnectionInterceptor ConnectionInterceptor = new EFConnectionInterceptor(); public class CurrentContext : DbContext { public CurrentContext() { this.BindInterceptor(ConnectionInterceptor); } public DbSet<Customer> Customers { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"Data Source=(localdb)\ProjectsV13;Initial Catalog=TestDB;"); } }
Now let's insert some data to the database and then retrieve the data from the database.
static void Main(string[] args) { DbInterception.Add(ConnectionInterceptor); using (var context = new CurrentContext()) { var list = new List<Customer>(); list.Add(new Customer() { Name = "Customer_A", IsActive = true }); list.Add(new Customer() { Name = "Customer_B", IsActive = true }); list.Add(new Customer() { Name = "Customer_C", IsActive = true }); context.Customers.AddRange(list); context.SaveChanges(); } using (var context = new CurrentContext()) { var list = context.Customers.ToList(); } }
Let's run your application in debug mode, and you will see all the information related to connection on the console window.
Intercepted on: EFConnectionInterceptor.Opening: Opening connection to database 'TestDB' on server '(localdb)\ProjectsV13'. Intercepted on: EFConnectionInterceptor.Opened: Opened connection to database 'TestDB' on server '(localdb)\ProjectsV13'. Intercepted on: EFConnectionInterceptor.Closing: Closing connection to database 'TestDB' on server '(localdb)\ProjectsV13'. Intercepted on: EFConnectionInterceptor.Closed: Closed connection to database 'TestDB' on server '(localdb)\ProjectsV13'. Intercepted on: EFConnectionInterceptor.Opening: Opening connection to database 'TestDB' on server '(localdb)\ProjectsV13'. Intercepted on: EFConnectionInterceptor.Opened: Opened connection to database 'TestDB' on server '(localdb)\ProjectsV13'. Intercepted on: EFConnectionInterceptor.Closing: Closing connection to database 'TestDB' on server '(localdb)\ProjectsV13'. Intercepted on: EFConnectionInterceptor.Closed: Closed connection to database 'TestDB' on server '(localdb)\ProjectsV13'.
ZZZ Projects