在Entity Framework中拦截数据库命令
在这里,您将学习如何拦截EF 6中DbContext执行的数据库命令。
EF 6通过实现IDbCommandInterceptor接口提供了拦截上下文的能力。IDbCommandInterceptor接口包括一些方法,这些方法可以拦截DbContext的实例,并允许你在上下文执行命令或查询之前或之后执行你的自定义逻辑。DbContext使用ADO.NET中的方法执行命令和查询,如ExecuteNonQuery, ExecuteScalar和ExecuteReader,您可以通过实现NonQueryExecuted和NonQueryExecuting等方法来拦截它们。
要拦截DbContext的一个实例,首先,创建自定义类并实现IDbCommandInterceptor,如下所示:
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提供了六个实现方法。它记录命令以供演示,但您可以在这里编写自定义逻辑。
接下来,您需要使用配置文件或基于代码的配置来配置拦截器。
在app.config文件中配置拦截器,如下所示:
<entityFramework>
<interceptors>
<interceptor type="EF6DBFirstTutorials.EFCommandInterceptor, EF6DBFirstTutorials">
</interceptor>
</interceptors>
</entityFramework>
如果使用基于代码的配置,则按如下所示配置。
public class FE6CodeConfig : DbConfiguration
{
public FE6CodeConfig()
{
this.AddInterceptor(new EFCommandInterceptor());
}
}
所以现在,当实例DbContext执行命令或查询时,我们可以记录命令。考虑下面的例子。
var newStudent = new Student() { FirstName = "Bill" };
using (var context = new SchoolDBEntities())
{
context.Students.Add(newStudent);
context.SaveChanges();
}
上面的示例将记录以下内容。
Output:
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()
参考
https://www.entityframeworktutorial.net/
https://msdn.microsoft.com/