/// <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、修复了网上提供的正则表达式特殊情况下报错问题
|