支持[#88]QueryFilter

This commit is contained in:
xuejiaming 2021-12-31 21:35:33 +08:00
parent 04ef52439d
commit 07fd59f288
13 changed files with 122 additions and 143 deletions

View File

@ -17,5 +17,17 @@ namespace Sample.NoShardingMultiLevel
modelBuilder.ApplyConfiguration(new CompanyMap());
modelBuilder.ApplyConfiguration(new DepartmentMap());
}
public override void Dispose()
{
Console.WriteLine("DefaultDbContext dispose");
base.Dispose();
}
public override ValueTask DisposeAsync()
{
Console.WriteLine("DefaultDbContext disposeasync");
return base.DisposeAsync();
}
}
}

View File

@ -48,7 +48,6 @@ namespace Sample.SqlServerShardingTable
entity.Property(o => o.Id).ValueGeneratedNever();
entity.Property(o=>o.Name).IsRequired().IsUnicode(false).HasMaxLength(50);
entity.HasQueryFilter(o => o.IsDelete == false);
entity.HasQueryFilter(o => o.Name == "123");
entity.ToTable(nameof(MultiShardingOrder));
});
}

View File

@ -131,8 +131,7 @@ namespace ShardingCore
services.TryAddSingleton<IShardingBootstrapper, ShardingBootstrapper>();
services.TryAddSingleton<IQueryTracker, QueryTracker>();
services.TryAddSingleton<IShardingTrackQueryExecutor, DefaultShardingTrackQueryExecutor>();
services.TryAddSingleton<INativeEnumeratorTrackQueryExecutor, NativeEnumeratorTrackQueryExecutor>();
services.TryAddSingleton<INativeSingleTrackQueryExecutor, NativeSingleTrackQueryExecutor>();
services.TryAddSingleton<INativeTrackQueryExecutor, NativeTrackQueryExecutor>();
services.TryAddShardingJob();
return services;

View File

@ -17,40 +17,42 @@ namespace ShardingCore.Sharding.ShardingExecutors
{
public class DefaultShardingTrackQueryExecutor: IShardingTrackQueryExecutor
{
private static readonly MethodInfo NativeSingleTrackQueryExecutorTrack
= typeof(NativeSingleTrackQueryExecutor)
//对象查询追踪方法
private static readonly MethodInfo Track
= typeof(NativeTrackQueryExecutor)
.GetMethod(
nameof(NativeSingleTrackQueryExecutor.Track),
nameof(NativeTrackQueryExecutor.Track),
BindingFlags.Instance | BindingFlags.Public
);
private static readonly MethodInfo NativeSingleTrackQueryExecutorTrackAsync
= typeof(NativeSingleTrackQueryExecutor)
//对象查询追踪方法
private static readonly MethodInfo TrackAsync
= typeof(NativeTrackQueryExecutor)
.GetMethod(
nameof(NativeSingleTrackQueryExecutor.TrackAsync),
nameof(NativeTrackQueryExecutor.TrackAsync),
BindingFlags.Instance | BindingFlags.Public
);
private static readonly MethodInfo NativeEnumeratorTrackQueryExecutorTrack
= typeof(NativeEnumeratorTrackQueryExecutor)
//列表查询追踪方法
private static readonly MethodInfo TrackEnumerable
= typeof(NativeTrackQueryExecutor)
.GetMethod(
nameof(NativeEnumeratorTrackQueryExecutor.Track),
nameof(NativeTrackQueryExecutor.TrackEnumerable),
BindingFlags.Instance | BindingFlags.Public
);
private static readonly MethodInfo NativeEnumeratorTrackQueryExecutorTrackAsync
= typeof(NativeEnumeratorTrackQueryExecutor)
//列表查询追踪方法
private static readonly MethodInfo TrackAsyncEnumerable
= typeof(NativeTrackQueryExecutor)
.GetMethod(
nameof(NativeEnumeratorTrackQueryExecutor.TrackAsync),
nameof(NativeTrackQueryExecutor.TrackAsyncEnumerable),
BindingFlags.Instance | BindingFlags.Public
);
private readonly IShardingQueryExecutor _shardingQueryExecutor;
private readonly INativeEnumeratorTrackQueryExecutor _nativeEnumeratorTrackQueryExecutor;
private readonly INativeSingleTrackQueryExecutor _nativeSingleTrackQueryExecutor;
private readonly INativeTrackQueryExecutor _nativeTrackQueryExecutor;
public DefaultShardingTrackQueryExecutor(IShardingQueryExecutor shardingQueryExecutor, INativeEnumeratorTrackQueryExecutor nativeEnumeratorTrackQueryExecutor,INativeSingleTrackQueryExecutor nativeSingleTrackQueryExecutor)
public DefaultShardingTrackQueryExecutor(IShardingQueryExecutor shardingQueryExecutor, INativeTrackQueryExecutor nativeTrackQueryExecutor)
{
_shardingQueryExecutor = shardingQueryExecutor;
_nativeEnumeratorTrackQueryExecutor = nativeEnumeratorTrackQueryExecutor;
_nativeSingleTrackQueryExecutor = nativeSingleTrackQueryExecutor;
_nativeTrackQueryExecutor = nativeTrackQueryExecutor;
}
public TResult Execute<TResult>(IQueryCompilerContext queryCompilerContext)
{
@ -64,7 +66,16 @@ namespace ShardingCore.Sharding.ShardingExecutors
throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint());
}
//native query
var result = queryCompilerExecutor.GetQueryCompiler().Execute<TResult>(queryCompilerExecutor.GetReplaceQueryExpression());
//native query track
return ResultTrackExecute(result, queryCompilerContext, TrackEnumerable, Track);
}
private TResult ResultTrackExecute<TResult>(TResult result, IQueryCompilerContext queryCompilerContext,
MethodInfo enumerableMethod, MethodInfo entityMethod)
{
//native query
if (queryCompilerContext.IsParallelQuery() && queryCompilerContext.IsQueryTrack())
{
@ -77,28 +88,27 @@ namespace ShardingCore.Sharding.ShardingExecutors
{
if (queryCompilerContext.IsEnumerableQuery())
{
return NativeExecute(_nativeEnumeratorTrackQueryExecutor, NativeEnumeratorTrackQueryExecutorTrack,
return DoResultTrackExecute(enumerableMethod,
queryCompilerContext, queryEntityType, result);
}
else if (queryCompilerContext.IsEntityQuery())
{
return NativeExecute(_nativeSingleTrackQueryExecutor, NativeSingleTrackQueryExecutorTrack,
return DoResultTrackExecute(entityMethod,
queryCompilerContext, queryEntityType, result);
}
}
return result;
}
return result;
}
private TResult NativeExecute<TResult>(object executor, MethodInfo executorMethod,
private TResult DoResultTrackExecute<TResult>(MethodInfo executorMethod,
IQueryCompilerContext queryCompilerContext,Type queryEntityType, TResult result)
{
return (TResult)executorMethod
.MakeGenericMethod(queryEntityType)
.Invoke(executor, new object[] { queryCompilerContext, result });
.Invoke(_nativeTrackQueryExecutor, new object[] { queryCompilerContext, result });
}
#if !EFCORE2
@ -113,34 +123,14 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _shardingQueryExecutor.ExecuteAsync<TResult>(mergeQueryCompilerContext);
}
throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint());
}
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression(), cancellationToken);
//native query
if (queryCompilerContext.IsParallelQuery()&&queryCompilerContext.IsQueryTrack())
{
var queryEntityType = queryCompilerContext.GetQueryableEntityType();
var trackerManager =
(ITrackerManager)ShardingContainer.GetService(
typeof(ITrackerManager<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
if (trackerManager.EntityUseTrack(queryEntityType))
{
if (queryCompilerContext.IsEnumerableQuery())
{
return NativeExecute(_nativeEnumeratorTrackQueryExecutor, NativeEnumeratorTrackQueryExecutorTrackAsync,
queryCompilerContext,queryEntityType, result);
}
else if (queryCompilerContext.IsEntityQuery())
{
return NativeExecute(_nativeSingleTrackQueryExecutor, NativeSingleTrackQueryExecutorTrackAsync,
queryCompilerContext, queryEntityType, result);
}
}
return result;
}
return result;
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression(), cancellationToken);
//native query track
return ResultTrackExecute(result, queryCompilerContext, TrackAsyncEnumerable, TrackAsync);
}
#endif
#if EFCORE2
@ -156,31 +146,11 @@ namespace ShardingCore.Sharding.ShardingExecutors
}
throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint());
}
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression());
//native query
if (queryCompilerContext.IsParallelQuery()&&queryCompilerContext.IsQueryTrack())
{
var queryEntityType = queryCompilerContext.GetQueryableEntityType();
var trackerManager =
(ITrackerManager)ShardingContainer.GetService(
typeof(ITrackerManager<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
if (trackerManager.EntityUseTrack(queryEntityType))
{
if (queryCompilerContext.IsEnumerableQuery())
{
return NativeExecute(_nativeEnumeratorTrackQueryExecutor, NativeEnumeratorTrackQueryExecutorTrack,
queryCompilerContext, queryEntityType, result);
}
else if (queryCompilerContext.IsEntityQuery())
{
return NativeExecute(_nativeSingleTrackQueryExecutor, NativeSingleTrackQueryExecutorTrack,
queryCompilerContext, queryEntityType, result);
}
}
return result;
}
return result;
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression());
//native query track
return ResultTrackExecute(result, queryCompilerContext, TrackAsyncEnumerable, Track);
}
public Task<TResult> ExecuteAsync<TResult>(IQueryCompilerContext queryCompilerContext, CancellationToken cancellationToken)
@ -194,31 +164,11 @@ namespace ShardingCore.Sharding.ShardingExecutors
}
throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint());
}
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression(), cancellationToken);
//native query
if (queryCompilerContext.IsParallelQuery()&&queryCompilerContext.IsQueryTrack())
{
var queryEntityType = queryCompilerContext.GetQueryableEntityType();
var trackerManager =
(ITrackerManager)ShardingContainer.GetService(
typeof(ITrackerManager<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
if (trackerManager.EntityUseTrack(queryEntityType))
{
if (queryCompilerContext.IsEnumerableQuery())
{
return NativeExecute(_nativeEnumeratorTrackQueryExecutor, NativeEnumeratorTrackQueryExecutorTrack,
queryCompilerContext, queryEntityType, result);
}
else if (queryCompilerContext.IsEntityQuery())
{
return NativeExecute(_nativeSingleTrackQueryExecutor, NativeSingleTrackQueryExecutorTrack,
queryCompilerContext, queryEntityType, result);
}
}
return result;
}
return result;
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression(), cancellationToken);
//native query track
return ResultTrackExecute(result, queryCompilerContext, TrackEnumerable, TrackAsync);
}
#endif
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries
{
public interface INativeEnumeratorTrackQueryExecutor
{
IEnumerable<TResult> Track<TResult>(IQueryCompilerContext queryCompilerContext, IEnumerable<TResult> enumerable);
IAsyncEnumerable<TResult> TrackAsync<TResult>(IQueryCompilerContext queryCompilerContext, IAsyncEnumerable<TResult> asyncEnumerable);
}
}

View File

@ -7,9 +7,11 @@ using ShardingCore.Sharding.ShardingExecutors.Abstractions;
namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries
{
public interface INativeSingleTrackQueryExecutor
public interface INativeTrackQueryExecutor
{
TResult Track<TResult>(IQueryCompilerContext queryCompilerContext, TResult resultTask);
Task<TResult> TrackAsync<TResult>(IQueryCompilerContext queryCompilerContext, Task<TResult> resultTask);
IEnumerable<TResult> TrackEnumerable<TResult>(IQueryCompilerContext queryCompilerContext, IEnumerable<TResult> enumerable);
IAsyncEnumerable<TResult> TrackAsyncEnumerable<TResult>(IQueryCompilerContext queryCompilerContext, IAsyncEnumerable<TResult> asyncEnumerable);
}
}

View File

@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Sharding.Enumerators.TrackerEnumerables;
using ShardingCore.Sharding.Enumerators.TrackerEnumerators;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries
{
public class NativeEnumeratorTrackQueryExecutor: INativeEnumeratorTrackQueryExecutor
{
public IEnumerable<TResult> Track<TResult>(IQueryCompilerContext queryCompilerContext, IEnumerable<TResult> enumerable)
{
return new TrackEnumerable<TResult>(queryCompilerContext.GetShardingDbContext(), enumerable);
}
public IAsyncEnumerable<TResult> TrackAsync<TResult>(IQueryCompilerContext queryCompilerContext,IAsyncEnumerable<TResult> asyncEnumerable)
{
return new AsyncTrackerEnumerable<TResult>(queryCompilerContext.GetShardingDbContext(), asyncEnumerable);
}
}
}

View File

@ -6,14 +6,15 @@ using System.Threading.Tasks;
using ShardingCore.Core.QueryTrackers;
using ShardingCore.Core.TrackerManagers;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators.TrackerEnumerables;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries
{
public class NativeSingleTrackQueryExecutor: INativeSingleTrackQueryExecutor
public class NativeTrackQueryExecutor : INativeTrackQueryExecutor
{
private readonly IQueryTracker _queryTracker;
public NativeSingleTrackQueryExecutor(IQueryTracker queryTracker)
public NativeTrackQueryExecutor(IQueryTracker queryTracker)
{
_queryTracker = queryTracker;
}
@ -41,6 +42,16 @@ namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries
var result = await resultTask;
return Track(queryCompilerContext, result);
}
public IEnumerable<TResult> TrackEnumerable<TResult>(IQueryCompilerContext queryCompilerContext, IEnumerable<TResult> enumerable)
{
return new TrackEnumerable<TResult>(queryCompilerContext.GetShardingDbContext(), enumerable);
}
public IAsyncEnumerable<TResult> TrackAsyncEnumerable<TResult>(IQueryCompilerContext queryCompilerContext, IAsyncEnumerable<TResult> asyncEnumerable)
{
return new AsyncTrackerEnumerable<TResult>(queryCompilerContext.GetShardingDbContext(), asyncEnumerable);
}
}
}

View File

@ -34,6 +34,7 @@ namespace ShardingCore.Core.Internal.Visitors
/// </summary>
private readonly bool _shardingTableRoute;
private Expression<Func<string, bool>> _where = x => true;
private bool useQueryFilterOnFirstWhere = false;
private readonly ShardingPredicateResult _noShardingPredicateResult = new ShardingPredicateResult(false, null);
@ -46,6 +47,15 @@ namespace ShardingCore.Core.Internal.Visitors
public Expression<Func<string, bool>> GetRouteParseExpression()
{
if (!useQueryFilterOnFirstWhere)
{
useQueryFilterOnFirstWhere = true;
if (_entityMetadata.QueryFilterExpression != null)
{
var newWhere= Resolve(_entityMetadata.QueryFilterExpression);
_where = _where.And(newWhere);
}
}
return _where;
}
@ -59,13 +69,13 @@ namespace ShardingCore.Core.Internal.Visitors
var isShardingKey = false;
if (_shardingTableRoute)
{
isShardingKey = _entityMetadata.ShardingTableProperties.ContainsKey(member.Member.Name);
isShardingKey = _entityMetadata.ShardingTableProperties.ContainsKey(member.Member.Name);
}
else
{
isShardingKey = _entityMetadata.ShardingDataSourceProperties.ContainsKey(member.Member.Name);
}
return new ShardingPredicateResult(isShardingKey, isShardingKey?member.Member.Name:null);
return new ShardingPredicateResult(isShardingKey, isShardingKey ? member.Member.Name : null);
}
}
@ -168,7 +178,7 @@ namespace ShardingCore.Core.Internal.Visitors
{
if (unaryExpression.Operand is LambdaExpression lambdaExpression)
{
var newWhere = Resolve(lambdaExpression);
var newWhere = DoResolve(lambdaExpression);
_where = _where.And(newWhere);
}
}
@ -177,6 +187,22 @@ namespace ShardingCore.Core.Internal.Visitors
return base.VisitMethodCall(node);
}
private Expression<Func<string, bool>> DoResolve(LambdaExpression lambdaExpression)
{
if (!useQueryFilterOnFirstWhere)
{
useQueryFilterOnFirstWhere = true;
if (_entityMetadata.QueryFilterExpression != null)
{
var body = Expression.AndAlso(lambdaExpression.Body, _entityMetadata.QueryFilterExpression.Body);
var lambda = Expression.Lambda(body, lambdaExpression.Parameters[0]);
return Resolve(lambda);
}
}
return Resolve(lambdaExpression);
}
private Expression<Func<string, bool>> Resolve(Expression expression)
{

View File

@ -428,6 +428,11 @@ namespace ShardingCore.Test
var list3 = await queryable1.ToListAsync();
Assert.Equal(1, list3.Count());
Assert.Contains(list3, o => o.Name == "name_300");
var firstOrDefaultAsync =await queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefaultAsync();
Assert.NotNull(firstOrDefaultAsync);
var firstOrDefault = queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefault();
Assert.NotNull(firstOrDefault);
Assert.Equal(firstOrDefaultAsync,firstOrDefault);
}
[Fact]

View File

@ -400,6 +400,11 @@ namespace ShardingCore.Test2x
var list3 = await queryable1.ToListAsync();
Assert.Equal(1, list3.Count());
Assert.Contains(list3, o => o.Name == "name_300");
var firstOrDefaultAsync = await queryable1.OrderBy(o=>o.DateOfMonth).FirstOrDefaultAsync();
Assert.NotNull(firstOrDefaultAsync);
var firstOrDefault = queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefault();
Assert.NotNull(firstOrDefault);
Assert.Equal(firstOrDefaultAsync, firstOrDefault);
}
[Fact]

View File

@ -399,6 +399,11 @@ namespace ShardingCore.Test3x
var list3 = await queryable1.ToListAsync();
Assert.Equal(1, list3.Count());
Assert.Contains(list3, o => o.Name == "name_300");
var firstOrDefaultAsync = await queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefaultAsync();
Assert.NotNull(firstOrDefaultAsync);
var firstOrDefault = queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefault();
Assert.NotNull(firstOrDefault);
Assert.Equal(firstOrDefaultAsync, firstOrDefault);
}
[Fact]

View File

@ -399,6 +399,11 @@ namespace ShardingCore.Test5x
var list3 = await queryable1.ToListAsync();
Assert.Equal(1, list3.Count());
Assert.Contains(list3, o => o.Name == "name_300");
var firstOrDefaultAsync = await queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefaultAsync();
Assert.NotNull(firstOrDefaultAsync);
var firstOrDefault = queryable1.OrderBy(o=>o.DateOfMonth).FirstOrDefault();
Assert.NotNull(firstOrDefault);
Assert.Equal(firstOrDefaultAsync, firstOrDefault);
}
[Fact]