添加对ignoreQueryFilters的支持[#101]
This commit is contained in:
parent
621d1fd29f
commit
09ad633e4a
|
@ -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----");
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace Sample.SqlServer
|
|||
|
||||
public bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext)
|
||||
{
|
||||
return queryCompilerContext.isUnion();
|
||||
return queryCompilerContext.IsUnion();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ShardingCore.Core.NotSupportShardingProviders
|
|||
|
||||
public bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext)
|
||||
{
|
||||
return queryCompilerContext.isUnion();
|
||||
return queryCompilerContext.IsUnion();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,6 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
|
|||
/// <returns></returns>
|
||||
bool IsQueryTrack();
|
||||
|
||||
bool isUnion();
|
||||
bool IsUnion();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
//{
|
||||
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue