Перехват CRUD-операций над базой данных с использованием EF6 и фильтрация логов - PullRequest
0 голосов
/ 08 декабря 2018

Я пытаюсь реализовать ведение журналов в своем приложении для форм Windows, и у меня есть этот код, который позволяет мне перехватывать операции CRUD при использовании Entity Framework 6:

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

Теперь это все хорошо и работает, я имею в виду, что это приятная небольшая функция ... Но я хочу войти в свою базу данных, только когда пользователь вставил или удалил запись.

Поэтому мне нужно имя команды (Вставить или Удалить), имя таблицы , идентификатор строки и еще одно поле из этой таблицы ...

Теперь я вижу, что у меня есть 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 ]

0 голосов
/ 08 декабря 2018

В качестве опции вместо перехвата выполнения команды вы можете войти в слой бизнес-логики:

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;
        }
    }
    //...
}
0 голосов
/ 08 декабря 2018

Только с силой 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();
   }
}

При необработанных запросах вам нужен анализатор.

...