|
|
@@ -1,19 +1,21 @@
|
|
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
|
using System.Data.Common;
|
|
|
using System.Text.RegularExpressions;
|
|
|
+using Microsoft.EntityFrameworkCore;
|
|
|
|
|
|
namespace Masuit.Tools.Core;
|
|
|
|
|
|
-public class QueryWithNoLockDbCommandInterceptor : DbCommandInterceptor
|
|
|
+/// <summary>
|
|
|
+/// WITH (NOLOCK)全局拦截器,仅限SQL Server使用
|
|
|
+/// </summary>
|
|
|
+/// <param name="enableGlobalNolock">全局启用,无需手动调用WithNolock扩展</param>
|
|
|
+public class WithNoLockInterceptor(bool enableGlobalNolock = false) : DbCommandInterceptor
|
|
|
{
|
|
|
- private static readonly Regex TableAliasRegex = new Regex(@"(?<tableAlias>AS \[[a-zA-Z]\w*\](?! WITH \(NOLOCK\)))", RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
|
|
+ private static readonly Regex TableRegex = new Regex(@"(?<table>\[\w+\] 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)"
|
|
|
- );
|
|
|
+ AddWithNoLock(command);
|
|
|
return base.ScalarExecuting(command, eventData, result);
|
|
|
}
|
|
|
|
|
|
@@ -22,31 +24,24 @@ public class QueryWithNoLockDbCommandInterceptor : DbCommandInterceptor
|
|
|
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)"
|
|
|
- );
|
|
|
+ AddWithNoLock(command);
|
|
|
return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);
|
|
|
}
|
|
|
|
|
|
#else
|
|
|
+
|
|
|
public override ValueTask<InterceptionResult<object>> ScalarExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<object> result,
|
|
|
CancellationToken cancellationToken = new CancellationToken())
|
|
|
{
|
|
|
- command.CommandText = TableAliasRegex.Replace(
|
|
|
- command.CommandText,
|
|
|
- "${tableAlias} WITH (NOLOCK)"
|
|
|
- );
|
|
|
+ AddWithNoLock(command);
|
|
|
return base.ScalarExecutingAsync(command, eventData, result, cancellationToken);
|
|
|
}
|
|
|
+
|
|
|
#endif
|
|
|
|
|
|
public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
|
|
|
{
|
|
|
- command.CommandText = TableAliasRegex.Replace(
|
|
|
- command.CommandText,
|
|
|
- "${tableAlias} WITH (NOLOCK)"
|
|
|
- );
|
|
|
+ AddWithNoLock(command);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -55,22 +50,38 @@ CancellationToken cancellationToken = new CancellationToken())
|
|
|
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)"
|
|
|
- );
|
|
|
+ AddWithNoLock(command);
|
|
|
return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
|
|
|
}
|
|
|
|
|
|
#else
|
|
|
+
|
|
|
public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result,
|
|
|
CancellationToken cancellationToken = new CancellationToken())
|
|
|
{
|
|
|
- command.CommandText = TableAliasRegex.Replace(
|
|
|
- command.CommandText,
|
|
|
- "${tableAlias} WITH (NOLOCK)"
|
|
|
- );
|
|
|
+ AddWithNoLock(command);
|
|
|
return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
|
|
|
}
|
|
|
#endif
|
|
|
+
|
|
|
+ private void AddWithNoLock(DbCommand command)
|
|
|
+ {
|
|
|
+ // 检查查询是否有标记
|
|
|
+ if (enableGlobalNolock || command.CommandText.StartsWith("-- NOLOCK"))
|
|
|
+ {
|
|
|
+ command.CommandText = TableRegex.Replace(command.CommandText, "${table} WITH (NOLOCK)");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+public static class WithNoLockExt
|
|
|
+{
|
|
|
+ public static IQueryable<T> WithNolock<T>(this IQueryable<T> queryable)
|
|
|
+ {
|
|
|
+ return queryable.TagWith("-- NOLOCK");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+[Obsolete("请使用WithNoLockInterceptor替代")]
|
|
|
+public class QueryWithNoLockDbCommandInterceptor : WithNoLockInterceptor
|
|
|
+{ }
|