/// <summary> /// ef實現withnolock,給表名后面添加with(nolock),不適用.net core /// </summary> public class WithNoLockInterceptor : DbCommandInterceptor { private static readonly Regex TableAliasRegex = new Regex(@"(?<tableAlias>\[dbo\].\[\w+\] AS \[Extent\d+\](?! WITH\(NOLOCK\)))", RegexOptions.Multiline | RegexOptions.IgnoreCase); /// <summary> /// https://www.bbsmax.com/A/8Bz8V6V65x/ /// 建議不要為標記為 ThreadStaticAttribute 的字段指定初始值,因為這樣的初始化只會發生一次,因此在類構造函數執行時只會影響一個線程。 /// 在不指定初始值的情況下,如果它是值類型,可依賴初始化為其默認值的字段,如果它是引用類型,則可依賴初始化為空引用的字段。 /// </summary> [ThreadStatic] public static bool Uselocking; [ThreadStatic] public static string CommandText; public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { if (!Uselocking) { command.CommandText = TableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH(NOLOCK) "); CommandText = command.CommandText; } //System.IO.File.AppendAllText("D:\\1.txt", "Uselocking=" + Uselocking.ToString() + "~" + CommandText + "\r\n\r\n"); } public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { if (!Uselocking) { command.CommandText = TableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH(NOLOCK) "); CommandText = command.CommandText; } //System.IO.File.AppendAllText("D:\\1.txt", "Uselocking=" + Uselocking.ToString() + "~" + CommandText + "\r\n\r\n"); }
使用:在Global.cs的Application_Start()里面添加如下語句,生成的sql會自動加上with(nolock)
//ef命令攔截器
DbInterception.Add(new WithNoLockInterceptor());
如果執行的sql語句需要鎖表,增加如下擴展即可
public static class WithNoLockExtensions { /// <summary> /// 部分查詢需要使用鎖查詢的,可以調用此擴展(默認全局查詢使用with(nolock)) /// 參考:https://github.com/aspnetboilerplate/aspnetboilerplate/issues/1637/ /// 示例: /// 1、query.OrderByCustom(filters.orderFields).Select({...}).UseLocking(querable => querable.PagingAsync(filters.page, filters.rows)); /// 2、repository.EntitiesAsNoTracking.Select(...).UseLocking(item=>item.FirstOrDefaultAsync()); /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="TResult"></typeparam> /// <param name="query"></param> /// <param name="queryAction"></param> /// <returns></returns> public static TResult UseLocking<T, TResult>(this IQueryable<T> query, Func<IQueryable<T>, TResult> queryAction) { WithNoLockInterceptor.Uselocking = true; //System.IO.File.AppendAllText("D:\\2.txt", $"更改了Uselocking{WithNoLockInterceptor.Uselocking}狀態\r\n\r\n"); TResult queryableResult = default(TResult); try { queryableResult = queryAction(query); } finally { WithNoLockInterceptor.Uselocking = false; } //System.IO.File.AppendAllText("D:\\2.txt", $"更改了Uselocking2{WithNoLockInterceptor.Uselocking}狀態\r\n\r\n"); return queryableResult; }
1、修復了網上提供的正則表達式特殊情況下報錯問題