添加对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(); var xxxaaa = await _defaultTableDbContext.Set<SysUserSalary>().FirstOrDefaultAsync();
Console.WriteLine("----0----"); 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----"); Console.WriteLine("----1----");
var xxx1 = await _defaultTableDbContext.Set<SysUserSalary>().OrderByDescending(o=>o.DateOfMonth).LastOrDefaultAsync(); var xxx1 = await _defaultTableDbContext.Set<SysUserSalary>().OrderByDescending(o=>o.DateOfMonth).LastOrDefaultAsync();
Console.WriteLine("----2----"); Console.WriteLine("----2----");

View File

@ -139,7 +139,7 @@ namespace Sample.SqlServer
public bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext) 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() public async Task<IActionResult> Query2()
{ {
var multiOrder =await _myDbContext.Set<MultiShardingOrder>().Where(o=>o.Id== 232398109278351360).FirstOrDefaultAsync(); 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 longs = new []{ 232398109278351360 , 255197859283087360 };
var multiOrders = await _myDbContext.Set<MultiShardingOrder>().Where(o => longs.Contains(o.Id)).ToListAsync(); var multiOrders = await _myDbContext.Set<MultiShardingOrder>().Where(o => longs.Contains(o.Id)).ToListAsync();
var dateTime = new DateTime(2021, 11, 1); var dateTime = new DateTime(2021, 11, 1);

View File

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

View File

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

View File

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

View File

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

View File

@ -6,6 +6,7 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query;
using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.VirtualDatabase; using ShardingCore.Core.VirtualDatabase;
@ -36,6 +37,7 @@ namespace ShardingCore.Core.Internal.Visitors
private Expression<Func<string, bool>> _where = x => true; private Expression<Func<string, bool>> _where = x => true;
private LambdaExpression _entityLambdaExpression; private LambdaExpression _entityLambdaExpression;
private readonly ShardingPredicateResult _noShardingPredicateResult = new ShardingPredicateResult(false, null); 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) 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() public Expression<Func<string, bool>> GetRouteParseExpression()
{ {
if (_entityMetadata.QueryFilterExpression != null) if (_entityMetadata.QueryFilterExpression != null&&!isIgnoreQueryFilter)
{ {
if (_entityLambdaExpression == null) if (_entityLambdaExpression == null)
{ {
@ -243,34 +245,40 @@ namespace ShardingCore.Core.Internal.Visitors
protected override Expression VisitMethodCall(MethodCallExpression node) protected override Expression VisitMethodCall(MethodCallExpression node)
{ {
if (node.Method.Name == nameof(Queryable.Where)) switch (node.Method.Name)
{ {
if (node.Arguments[1] is UnaryExpression unaryExpression) case nameof(EntityFrameworkQueryableExtensions.IgnoreQueryFilters): isIgnoreQueryFilter = true;break;
{ case nameof(Queryable.Where): CombineEntityLambdaExpression(node);break;
if (unaryExpression.Operand is LambdaExpression lambdaExpression)
{
if (lambdaExpression.Parameters[0].Type == _entityMetadata.EntityType)
{
if (_entityLambdaExpression == null)
{
_entityLambdaExpression = lambdaExpression;
}
else
{
var body = Expression.AndAlso(_entityLambdaExpression.Body, lambdaExpression.Body);
var lambda = Expression.Lambda(body, _entityLambdaExpression.Parameters[0]);
_entityLambdaExpression = lambda;
}
}
//var newWhere = DoResolve(lambdaExpression);
//_where = _where.And(newWhere);
}
}
} }
return base.VisitMethodCall(node); return base.VisitMethodCall(node);
} }
private void CombineEntityLambdaExpression(MethodCallExpression node)
{
if (node.Arguments[1] is UnaryExpression unaryExpression)
{
if (unaryExpression.Operand is LambdaExpression lambdaExpression)
{
if (lambdaExpression.Parameters[0].Type == _entityMetadata.EntityType)
{
if (_entityLambdaExpression == null)
{
_entityLambdaExpression = lambdaExpression;
}
else
{
var body = Expression.AndAlso(_entityLambdaExpression.Body, lambdaExpression.Body);
var lambda = Expression.Lambda(body, _entityLambdaExpression.Parameters[0]);
_entityLambdaExpression = lambda;
}
}
//var newWhere = DoResolve(lambdaExpression);
//_where = _where.And(newWhere);
}
}
}
//private Expression<Func<string, bool>> DoResolve(LambdaExpression lambdaExpression) //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.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using ShardingCore.Core.EntityMetadatas;
namespace ShardingCore namespace ShardingCore
{ {
@ -148,5 +149,16 @@ namespace ShardingCore
{ {
return GetRequiredVirtualDataSourceManager(shardingDbContextType).GetCurrentVirtualDataSource()??throw new InvalidOperationException("cant resolve CurrentVirtualDataSource"); 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.VirtualDatabase;
using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Visitors.Querys;
namespace ShardingCore.Utils namespace ShardingCore.Utils
{ {
@ -82,6 +83,22 @@ namespace ShardingCore.Utils
return visitor.GetQueryEntities(); 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();
}
} }
} }