C# entityframework生成sql语句添加with(nolock)最优解决方案
/// <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、修复了网上提供的正则表达式特殊情况下报错问题