代码之家  ›  专栏  ›  技术社区  ›  Whirlwind

使用EF6和筛选日志截取数据库上的CRUD操作

  •  1
  • Whirlwind  · 技术社区  · 6 年前

    我正在尝试在我的Windows窗体应用程序中实现日志记录,我有这段代码,它允许我在使用Entity Framework 6时拦截CRUD操作:

     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);
            }
        }
    

    然后我像这样添加拦截器:

    public class FE6CodeConfig : DbConfiguration
    {
        public FE6CodeConfig()
        {
            this.AddInterceptor(new EFCommandInterceptor());
        }
    }
    

    现在这一切都很好,而且很有效,我的意思是这是一个很好的小功能……但是,我只想在用户插入或删除记录时登录到我的数据库。

    所以我需要 命令名 (插入或删除) 表名 , 行ID ,表中还有一个字段…

    现在我看到我在这些方法中使用了dbcommand。有一个名为command text…的属性,它提供如下输出:

    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()
    

    我的意思是可能解析上面字符串中的所有内容……但是有没有更方便的方法来获得这些数据?

    2 回复  |  直到 6 年前
        1
  •  1
  •   eocron    6 年前

    只有ef的力量(没有测试代码,但我希望你能理解这个想法):

    public void MyContext : DbContext
    {
       public override int SaveChanges() //not relevant if it is new, you can do it in another method.
       {
           foreach(var e in this.ChangeTracker.Entries())
           {
               if(e.State == EntityState.Added)
               {
                  //log here
               }
           }
           return base.SaveChanges();
       }
    }
    

    对于原始查询,您需要解析器。

        2
  •  1
  •   Reza Aghaei    6 年前

    作为一个选项,您可以登录业务逻辑层,而不是截取命令执行:

    public class ProductBusiness
    {
        ILogger logger;
    
        //...
        public void Create(Product p)
        {
            try
            {
                using (var db = new MyDbContext())
                {
                    db.Products.Add(p);
                    db.SaveChanges();
                    logger.Log($"Create Product - {DateTime.Now} - Id:{p.Id}, Name:{p.Name}");
                }
            }
            catch (Exception ex)
            {
                logger.Log($"Error - {DateTime.Now} - {ex.ToString()}");
                throw;
            }
        }
        //...
    }