2017-10-21 238 views
4

在實體框架的核心,您可以覆蓋DbContextSaveChanges/SaveChangesAsync方法和基於像不同的狀態:EntityState.AddedEntityState.ModifiedEntityState.Deleted,您可以創建什麼時候和誰創建,修改或刪除某些記錄一些審計解決方案。您可以在操作前後保存實體的狀態。這裏所有的好東西都很完美是否可以攔截READ操作?

我們可以爲讀取/查詢/選擇/查看操作做類似的事嗎?

+0

爲什麼這應該關閉?這個問題有什麼問題? – user2818430

+0

看看如果https://stackoverflow.com/questions/45132553/objectstatemanager-objectstatemanagerchanged-in-entity-framework-core/45192985#45192985可以幫助 –

+0

由此你的意思是如何記錄SELECT語句或不同的東西? – Evk

回答

2

我挖了一點,發現IQueryable的實際執行是由EntityQueryProvider : IAsyncQueryProvider, IQueryProvider完成的。

所以...你覆蓋默認EntityQueryProvider做記錄:

public class LoggingQueryProvider : EntityQueryProvider 
    { 
     public LoggingQueryProvider(IQueryCompiler queryCompiler) : base(queryCompiler) { } 

     public override object Execute(Expression expression) 
     { 
      var result = base.Execute(expression); 
      //log 
      return result; 
     } 
     public override TResult Execute<TResult>(Expression expression) 
     { 
      var result = base.Execute<TResult>(expression); 
      //log 
      return result; 
     } 
     public override IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression expression) 
     { 
      var result = base.ExecuteAsync<TResult>(expression); 
      //log 
      return result; 
     } 
     public override Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken) 
     { 
      var result = base.ExecuteAsync<TResult>(expression, cancellationToken); 
      //log 
      return result; 
     } 
    } 

StartUp.ConfigureServices(IServiceCollection services)

services.AddDbContext<XPContext>(builder => 
     builder 
     .UseSqlServer(Configuration["TryDBConnectionString"]) 
     .ReplaceService<IAsyncQueryProvider, LoggingQueryProvider>() 
    ); 

配置的DbContext當你註冊它這不是很簡單的,但你應該能夠從表達式中獲得一些信息,如實體類型,並且您顯然可以訪問實際結果。異步方法看起來有點複雜,但...

+0

我喜歡擴展查詢提供者的想法,但你打算如何在沒有dbContext的情況下登錄到數據庫? –

+0

想到使用單獨的'DbContext' ... –

0

大多數策略都依賴於覆蓋SaveChanges()來審計數據,但您也可以通過重寫Dispose()方法來訪問其他數據。

當從數據庫查詢數據時,它將被添加到dbContext中,如果它被讀取但沒有被更改,它應該有EntityState.Unchanged

假設每個請求的新實例的一個典型的web應用風格DbContext範圍然後通過ID的查詢將意味着有一個在ChangeTracker與該狀態的單個條目的DbContext設置時。

你可以嘗試這樣的事:

public override void Dispose() 
{ 
    var unchanged = ChangeTracker.Entries() 
      .Where(x => x.EntityState == EntityState.Unchanged); 

    // log your unchanged entries here 

    base.Dispose(); 
} 

這不完全萬無一失,因爲你可能會在一個創建/更新過程中檢索某些表數據作爲驗證的一部分,或者你可能跨越共用同一個上下文多個存儲庫,因此您需要考慮哪些實體需要仔細審覈以及使用哪種訪問模式

+0

如何查詢'AsNoTracking()'? –

+0

@GertArnold正如我所說 - 不是萬無一失。假設OP可以控制所有查詢。現在你提到它'AsNoChangeTracking()'可以添加一個從審計中排除某些查詢的細粒度方法。 –

0

我建議您在更高級別進行日誌記錄。例如,如果您使用的是WebApi,則可以在OWIN管道級別登錄,從而記錄信息請求。
通過記錄低端數據來進行第二次猜測,並重新讀取醜陋的數據,並最終導致效率低下。

相關問題