添加对ignoreQueryFilters的支持[#101]

This commit is contained in:
xuejiaming 2022-01-28 16:32:12 +08:00
parent 621d1fd29f
commit 09ad633e4a
12 changed files with 210 additions and 39 deletions

View File

@ -224,7 +224,7 @@ namespace Sample.SqlServer.Controllers
var xxxaaa = await _defaultTableDbContext.Set<SysUserSalary>().FirstOrDefaultAsync();
Console.WriteLine("----0----");
var xxx = await _defaultTableDbContext.Set<SysUserSalary>().OrderByDescending(o=>o.DateOfMonth).FirstOrDefaultAsync();
var xxx = await _defaultTableDbContext.Set<SysUserSalary>().IgnoreQueryFilters().OrderByDescending(o=>o.DateOfMonth).FirstOrDefaultAsync();
Console.WriteLine("----1----");
var xxx1 = await _defaultTableDbContext.Set<SysUserSalary>().OrderByDescending(o=>o.DateOfMonth).LastOrDefaultAsync();
Console.WriteLine("----2----");

View File

@ -139,7 +139,7 @@ namespace Sample.SqlServer
public bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext)
{
return queryCompilerContext.isUnion();
return queryCompilerContext.IsUnion();
}
}
}

View File

@ -42,6 +42,7 @@ namespace Sample.SqlServerShardingTable.Controllers
public async Task<IActionResult> Query2()
{
var multiOrder =await _myDbContext.Set<MultiShardingOrder>().Where(o=>o.Id== 232398109278351360).FirstOrDefaultAsync();
var multiOrder1 =await _myDbContext.Set<MultiShardingOrder>().IgnoreQueryFilters().Where(o=>o.Id== 232398109278351360).FirstOrDefaultAsync();
var longs = new []{ 232398109278351360 , 255197859283087360 };
var multiOrders = await _myDbContext.Set<MultiShardingOrder>().Where(o => longs.Contains(o.Id)).ToListAsync();
var dateTime = new DateTime(2021, 11, 1);

View File

@ -20,7 +20,7 @@ namespace ShardingCore.Core.NotSupportShardingProviders
public bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext)
{
return queryCompilerContext.isUnion();
return queryCompilerContext.IsUnion();
}
}
}

View File

@ -32,6 +32,6 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
/// <returns></returns>
bool IsQueryTrack();
bool isUnion();
bool IsUnion();
}
}

View File

@ -104,9 +104,9 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _queryCompilerContext.IsQueryTrack();
}
public bool isUnion()
public bool IsUnion()
{
return _queryCompilerContext.isUnion();
return _queryCompilerContext.IsUnion();
}
public QueryCompilerExecutor GetQueryCompilerExecutor()

View File

@ -20,24 +20,23 @@ namespace ShardingCore.Sharding.ShardingExecutors
private readonly Expression _queryExpression;
private readonly IEntityMetadataManager _entityMetadataManager;
private readonly Type _shardingDbContextType;
private readonly IShardingEntityConfigOptions _entityConfigOptions;
private QueryCompilerExecutor _queryCompilerExecutor;
private bool? hasQueryCompilerExecutor;
private bool? _isNoTracking;
private bool _isUnion;
private readonly bool? _isNoTracking;
private readonly bool _isUnion;
private readonly bool _isParallelQuery;
private QueryCompilerContext(IShardingDbContext shardingDbContext, Expression queryExpression)
{
_shardingDbContextType = shardingDbContext.GetType();
_queryEntities = ShardingUtil.GetQueryEntitiesByExpression(queryExpression, _shardingDbContextType);
_isNoTracking = queryExpression.GetIsNoTracking();
_isUnion = queryExpression.GetIsUnion();
var compileParseResult = ShardingUtil.GetQueryCompileParseResultByExpression(queryExpression, _shardingDbContextType);
_queryEntities = compileParseResult.QueryEntities;
_isNoTracking = compileParseResult.IsNoTracking;
_isUnion = compileParseResult.IsUnion;
_shardingDbContext = shardingDbContext;
_queryExpression = queryExpression;
_entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(_shardingDbContextType));
_entityMetadataManager = ShardingContainer.GetRequiredEntityMetadataManager(_shardingDbContextType);
_entityConfigOptions = ShardingContainer.GetRequiredShardingEntityConfigOption(_shardingDbContextType);
//原生对象的原生查询如果是读写分离就需要启用并行查询
_isParallelQuery = shardingDbContext.IsUseReadWriteSeparation() && _shardingDbContext.CurrentIsReadWriteSeparation();
}
@ -93,11 +92,12 @@ namespace ShardingCore.Sharding.ShardingExecutors
}
}
public bool isUnion()
public bool IsUnion()
{
return _isUnion;
}
public QueryCompilerExecutor GetQueryCompilerExecutor()
{
if (!hasQueryCompilerExecutor.HasValue)

View File

@ -6,6 +6,7 @@ using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.VirtualDatabase;
@ -36,6 +37,7 @@ namespace ShardingCore.Core.Internal.Visitors
private Expression<Func<string, bool>> _where = x => true;
private LambdaExpression _entityLambdaExpression;
private readonly ShardingPredicateResult _noShardingPredicateResult = new ShardingPredicateResult(false, null);
private bool isIgnoreQueryFilter;
public QueryableRouteShardingTableDiscoverVisitor(EntityMetadata entityMetadata, Func<object, ShardingOperatorEnum, string, Expression<Func<string, bool>>> keyToTailWithFilter, bool shardingTableRoute)
{
@ -47,7 +49,7 @@ namespace ShardingCore.Core.Internal.Visitors
public Expression<Func<string, bool>> GetRouteParseExpression()
{
if (_entityMetadata.QueryFilterExpression != null)
if (_entityMetadata.QueryFilterExpression != null&&!isIgnoreQueryFilter)
{
if (_entityLambdaExpression == null)
{
@ -243,7 +245,16 @@ namespace ShardingCore.Core.Internal.Visitors
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == nameof(Queryable.Where))
switch (node.Method.Name)
{
case nameof(EntityFrameworkQueryableExtensions.IgnoreQueryFilters): isIgnoreQueryFilter = true;break;
case nameof(Queryable.Where): CombineEntityLambdaExpression(node);break;
}
return base.VisitMethodCall(node);
}
private void CombineEntityLambdaExpression(MethodCallExpression node)
{
if (node.Arguments[1] is UnaryExpression unaryExpression)
{
@ -268,9 +279,6 @@ namespace ShardingCore.Core.Internal.Visitors
}
}
return base.VisitMethodCall(node);
}
//private Expression<Func<string, bool>> DoResolve(LambdaExpression lambdaExpression)
//{

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShardingCore.Sharding.Visitors.Querys
{
public class CompileParseResult
{
public CompileParseResult(bool isUnion, bool? isNoTracking, bool isIgnoreFilter, ISet<Type> queryEntities)
{
IsUnion = isUnion;
IsNoTracking = isNoTracking;
IsIgnoreFilter = isIgnoreFilter;
QueryEntities = queryEntities;
}
/// <summary>
/// 是否使用了union查询
/// </summary>
public bool IsUnion { get; }
/// <summary>
/// 是否使用了追踪
/// </summary>
public bool? IsNoTracking { get; }
/// <summary>
/// 是否使用了忽略filter
/// </summary>
public bool IsIgnoreFilter { get; }
/// <summary>
/// 当前涉及到的查询对象
/// </summary>
public ISet<Type> QueryEntities { get; }
}
}

View File

@ -0,0 +1,98 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using ShardingCore.Core.TrackerManagers;
using ShardingCore.Extensions;
namespace ShardingCore.Sharding.Visitors.Querys
{
internal class QueryCompileParseVisitors : ExpressionVisitor
{
private readonly ITrackerManager _trackerManager;
private bool isUnion;
private bool? isNoTracking;
private bool isIgnoreFilter;
private readonly ISet<Type> shardingEntities = new HashSet<Type>();
public QueryCompileParseVisitors(ITrackerManager trackerManager)
{
_trackerManager = trackerManager;
}
public CompileParseResult GetCompileParseResult()
{
return new CompileParseResult(isUnion, isNoTracking, isIgnoreFilter, shardingEntities);
}
#if EFCORE2 || EFCORE3
protected override Expression VisitConstant(ConstantExpression node)
{
if (node.Value is IQueryable queryable)
{
shardingEntities.Add(queryable.ElementType);
}
return base.VisitConstant(node);
}
#endif
#if EFCORE5 || EFCORE6
protected override Expression VisitExtension(Expression node)
{
if (node is QueryRootExpression queryRootExpression)
{
shardingEntities.Add(queryRootExpression.EntityType.ClrType);
}
return base.VisitExtension(node);
}
#endif
protected override Expression VisitMethodCall(MethodCallExpression node)
{
switch (node.Method.Name)
{
case nameof(Queryable.Union): isUnion = true; break;
case nameof(EntityFrameworkQueryableExtensions.AsNoTracking): isNoTracking = true; break;
case nameof(EntityFrameworkQueryableExtensions.AsTracking): isNoTracking = false; break;
case nameof(EntityFrameworkQueryableExtensions.IgnoreQueryFilters): isIgnoreFilter = true; break;
case nameof(EntityFrameworkQueryableExtensions.Include):
case nameof(EntityFrameworkQueryableExtensions.ThenInclude): DiscoverQueryEntities(node); break;
}
return base.VisitMethodCall(node);
}
private void DiscoverQueryEntities(MethodCallExpression node)
{
var genericArguments = node.Type.GetGenericArguments();
for (var i = 0; i < genericArguments.Length; i++)
{
var genericArgument = genericArguments[i];
if (typeof(IEnumerable).IsAssignableFrom(genericArgument))
{
var arguments = genericArgument.GetGenericArguments();
foreach (var argument in arguments)
{
//if is db context model
if (_trackerManager.IsDbContextModel(argument))
{
shardingEntities.Add(argument);
}
}
}
if (!genericArgument.IsSimpleType())
{
//if is db context model
if (_trackerManager.IsDbContextModel(genericArgument))
{
shardingEntities.Add(genericArgument);
}
}
}
}
}
}

View File

@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ShardingCore.Core.EntityMetadatas;
namespace ShardingCore
{
@ -148,5 +149,16 @@ namespace ShardingCore
{
return GetRequiredVirtualDataSourceManager(shardingDbContextType).GetCurrentVirtualDataSource()??throw new InvalidOperationException("cant resolve CurrentVirtualDataSource");
}
public static IEntityMetadataManager GetRequiredEntityMetadataManager(Type shardingDbContextType)
{
return (IEntityMetadataManager)ServiceProvider.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(shardingDbContextType));
}
public static IEntityMetadataManager<TShardingDbContext> GetRequiredEntityMetadataManager<TShardingDbContext>()
where TShardingDbContext : DbContext, IShardingDbContext
{
return (IEntityMetadataManager<TShardingDbContext>)GetRequiredEntityMetadataManager(typeof(TShardingDbContext));
}
}
}

View File

@ -15,6 +15,7 @@ using ShardingCore.Core.TrackerManagers;
using ShardingCore.Core.VirtualDatabase;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Visitors.Querys;
namespace ShardingCore.Utils
{
@ -82,6 +83,22 @@ namespace ShardingCore.Utils
return visitor.GetQueryEntities();
}
/// <summary>
/// 获取次需要编译的表达式解析信息
/// </summary>
/// <param name="expression"></param>
/// <param name="dbContextType"></param>
/// <returns></returns>
public static CompileParseResult GetQueryCompileParseResultByExpression(Expression expression, Type dbContextType)
{
var trackerManager = (ITrackerManager)ShardingContainer.GetService(typeof(ITrackerManager<>).GetGenericType0(dbContextType));
QueryCompileParseVisitors visitor = new QueryCompileParseVisitors(trackerManager);
visitor.Visit(expression);
return visitor.GetCompileParseResult();
}
}
}