這一節介紹EF6怎麼記錄和攔截髮送給數據庫的查詢和操做命令。html
之前給了查看EF發送給數據庫的命令咱們須要藉助數據庫的追蹤工具或者第三方追蹤工具,如今EF6中提供了DbContext.Database.Log屬性(Action<string>類型),使用這個屬性咱們能夠很方便地記錄EF發送給數據庫的命令。web
下邊是一個栗子:數據庫
static void Main(string[] args) { using (EFDbContext context=new EFDbContext()) { context.Database.Log = Console.WriteLine; var std1 = context.Students.Find(1); std1.Name = "newName"; context.SaveChanges(); Console.ReadKey(); } }
輸出以下:api
在上邊的栗子中,Console.Write()方法屬於Action<string>類型,因此能夠賦值給Log屬性。能夠看到EF打開和關閉數據庫,執行查詢,和使用事務進行CUD都會被記錄下來。mvc
咱們也能夠自定義一個Action<string>委託的實例賦值給Log屬性:app
public class Logger { public static void Log(string message) { Console.WriteLine("EF Message: {0} ", message); } } class EF6Demo { public static void DBCommandLogging() { using (var context = new SchoolDBEntities()) { context.Database.Log = Logger.Log; var std1 = context.Students.Find(1); std1.Name = "newName"; context.SaveChanges(); Console.ReadKey(); } } }
EF6提供了攔截數據庫的接口IDbCommandIntercepter,這個接口提供了攔截EF發送給數據庫的命令的方法,咱們也能夠使用這個接口實如今context的操做執行前或執行後去作一些自定義的操做(相似mvc/api中的filter)。由於DbContext執行操做的底層實現是利用ADO.NET進行ExecuteNonQuery
, ExecuteScalar
, 和ExecuteReader,因此咱們能夠經過如
異步NonQueryExecuted、
NonQueryExecuting等方法進行攔截。
爲了實現SQL命令攔截咱們首先要定義一個實現IDbCommandIntercepter接口的類:ide
class EFCommandInterceptor : IDbCommandInterceptor { public void NonQueryExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { LogInfo("NonQueryExecuted", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText)); } public void NonQueryExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { LogInfo("NonQueryExecuting", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText)); } public void ReaderExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext) { LogInfo("ReaderExecuted", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText)); } public void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext) { LogInfo("ReaderExecuting", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText)); } public void ScalarExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { LogInfo("ScalarExecuted", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText)); } public void ScalarExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { LogInfo("ScalarExecuting", String.Format(" IsAsync: {0}, Command Text: {1}", interceptionContext.IsAsync, command.CommandText)); } private void LogInfo(string command, string commandText) { Console.WriteLine("Intercepted on: {0} :- {1} ", command, commandText); } }
能夠看出,IDbCommandInterceptor
接口提供了6個方法,分別用於在ADO.NET執行ExecuteNonQuery(),ExcuteReader(),ExcuteScalar()方法的執行前/後攔截命令。這個栗子目的是:記錄context的操做是不是異步和發送到數據庫的命令。咱們也能夠使用這些方法來實現自定義邏輯(和filter簡直如出一轍有木有)。工具
接下來把攔截器添加到配置中去,兩種實現方式:post
① 經過配置文件,在app.config或web.config中添加以下節點
<entityFramework> <interceptors> <interceptor type="EF6DBFirstTutorials.EFCommandInterceptor, EF6DBFirstTutorials"> </interceptor> </interceptors> </entityFramework>
②代碼配置
public class FE6CodeConfig : DbConfiguration { public FE6CodeConfig() { this.AddInterceptor(new EFCommandInterceptor()); } }
配置完成咱們就能夠記錄EF發送給數據庫的命令了,一個栗子:
var newStudent = new Student() { FirstName = "Bill" }; using (var context = new SchoolDBEntities()) { context.Students.Add(newStudent); context.SaveChanges(); }
栗子輸出爲:
Intercepted on: ReaderExecuting :- IsAsync: False, Command Text: INSERT [dbo].[Student]([FirstName], [StandardId], [LastName]) VALUES (@0, NULL, NULL) SELECT [StudentID], [RowVersion] FROM [dbo].[Student] WHERE @@ROWCOUNT > 0 AND [StudentID] = scope_identity() Intercepted on: ReaderExecuted :- IsAsync: False, Command Text: INSERT [dbo].[Student]([FirstName], [StandardId], [LastName]) VALUES (@0, NULL, NULL) SELECT [StudentID], [RowVersion] FROM [dbo].[Student] WHERE @@ROWCOUNT > 0 AND [StudentID] = scope_identity()
EF系列目錄連接:Entity Franmework系列教程彙總