EF Core 在 3.x 版本中增長了 Interceptor
,使得咱們能夠在發生低級別數據庫操做時做爲 EF Core 正常運行的一部分自動調用它們。 例如,打開鏈接、提交事務或執行命令時。git
因此咱們能夠自定義一個 Interceptor
來記錄執行的 sql 語句,也能夠經過 Interceptor
來實現 sql 語句的執行。github
這裏咱們能夠藉助 Interceptor
實現對於查詢語句的修改,自動給查詢語句加 (WITH NOLOCK)
,WITH NOLOCK
等效於 READ UNCOMMITED
(讀未提交)的事務級別,這樣會形成必定的髒讀,可是從效率上而言,是比較高效的,不會由於別的事務長時間未提交致使查詢阻塞,因此對於大數據場景下,查詢 SQL 加 NOLOCK
仍是比較有意義的sql
繼承 DbCommandInterceptor
,重寫查詢 sql 執行以前的操做,在執行 sql 以前增長 WITH(NOLOCK)
,實現代碼以下:數據庫
public class QueryWithNoLockDbCommandInterceptor : DbCommandInterceptor { private static readonly Regex TableAliasRegex = new Regex(@"(?<tableAlias>AS \[[a-zA-Z]\w*\](?! WITH \(NOLOCK\)))", RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.IgnoreCase); public override InterceptionResult<object> ScalarExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<object> result) { command.CommandText = TableAliasRegex.Replace( command.CommandText, "${tableAlias} WITH (NOLOCK)" ); return base.ScalarExecuting(command, eventData, result); } public override Task<InterceptionResult<object>> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<object> result, CancellationToken cancellationToken = new CancellationToken()) { command.CommandText = TableAliasRegex.Replace( command.CommandText, "${tableAlias} WITH (NOLOCK)" ); return base.ScalarExecutingAsync(command, eventData, result, cancellationToken); } public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result) { command.CommandText = TableAliasRegex.Replace( command.CommandText, "${tableAlias} WITH (NOLOCK)" ); return result; } public override Task<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result, CancellationToken cancellationToken = new CancellationToken()) { command.CommandText = TableAliasRegex.Replace( command.CommandText, "${tableAlias} WITH (NOLOCK)" ); return base.ReaderExecutingAsync(command, eventData, result, cancellationToken); } }
在註冊 DbContext
服務的時候,能夠配置 Interceptor
,配置以下:ide
var services = new ServiceCollection(); services.AddDbContext<TestDbContext>(options => { options .UseLoggerFactory(loggerFactory) .UseSqlServer(DbConnectionString) .AddInterceptors(new QueryWithNoLockDbCommandInterceptor()) ; });
經過 loggerFactory 記錄的日誌查看查詢執行的 sql 語句大數據
能夠看到查詢語句自動加上了 WITH (NOLOCK)
日誌