在實體框架的核心,您可以覆蓋DbContext
SaveChanges
/SaveChangesAsync
方法和基於像不同的狀態:EntityState.Added
或EntityState.Modified
或EntityState.Deleted
,您可以創建什麼時候和誰創建,修改或刪除某些記錄一些審計解決方案。您可以在操作前後保存實體的狀態。這裏所有的好東西都很完美是否可以攔截READ操作?
我們可以爲讀取/查詢/選擇/查看操作做類似的事嗎?
在實體框架的核心,您可以覆蓋DbContext
SaveChanges
/SaveChangesAsync
方法和基於像不同的狀態:EntityState.Added
或EntityState.Modified
或EntityState.Deleted
,您可以創建什麼時候和誰創建,修改或刪除某些記錄一些審計解決方案。您可以在操作前後保存實體的狀態。這裏所有的好東西都很完美是否可以攔截READ操作?
我們可以爲讀取/查詢/選擇/查看操作做類似的事嗎?
我挖了一點,發現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當你註冊它這不是很簡單的,但你應該能夠從表達式中獲得一些信息,如實體類型,並且您顯然可以訪問實際結果。異步方法看起來有點複雜,但...
我喜歡擴展查詢提供者的想法,但你打算如何在沒有dbContext的情況下登錄到數據庫? –
想到使用單獨的'DbContext' ... –
大多數策略都依賴於覆蓋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();
}
這不完全萬無一失,因爲你可能會在一個創建/更新過程中檢索某些表數據作爲驗證的一部分,或者你可能跨越共用同一個上下文多個存儲庫,因此您需要考慮哪些實體需要仔細審覈以及使用哪種訪問模式
如何查詢'AsNoTracking()'? –
@GertArnold正如我所說 - 不是萬無一失。假設OP可以控制所有查詢。現在你提到它'AsNoChangeTracking()'可以添加一個從審計中排除某些查詢的細粒度方法。 –
我建議您在更高級別進行日誌記錄。例如,如果您使用的是WebApi,則可以在OWIN管道級別登錄,從而記錄信息請求。
通過記錄低端數據來進行第二次猜測,並重新讀取醜陋的數據,並最終導致效率低下。
爲什麼這應該關閉?這個問題有什麼問題? – user2818430
看看如果https://stackoverflow.com/questions/45132553/objectstatemanager-objectstatemanagerchanged-in-entity-framework-core/45192985#45192985可以幫助 –
由此你的意思是如何記錄SELECT語句或不同的東西? – Evk