支持[#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 CompanyMap());
modelBuilder.ApplyConfiguration(new DepartmentMap()); 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.Id).ValueGeneratedNever();
entity.Property(o=>o.Name).IsRequired().IsUnicode(false).HasMaxLength(50); entity.Property(o=>o.Name).IsRequired().IsUnicode(false).HasMaxLength(50);
entity.HasQueryFilter(o => o.IsDelete == false); entity.HasQueryFilter(o => o.IsDelete == false);
entity.HasQueryFilter(o => o.Name == "123");
entity.ToTable(nameof(MultiShardingOrder)); entity.ToTable(nameof(MultiShardingOrder));
}); });
} }

View File

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

View File

@ -17,40 +17,42 @@ namespace ShardingCore.Sharding.ShardingExecutors
{ {
public class DefaultShardingTrackQueryExecutor: IShardingTrackQueryExecutor public class DefaultShardingTrackQueryExecutor: IShardingTrackQueryExecutor
{ {
private static readonly MethodInfo NativeSingleTrackQueryExecutorTrack //对象查询追踪方法
= typeof(NativeSingleTrackQueryExecutor) private static readonly MethodInfo Track
= typeof(NativeTrackQueryExecutor)
.GetMethod( .GetMethod(
nameof(NativeSingleTrackQueryExecutor.Track), nameof(NativeTrackQueryExecutor.Track),
BindingFlags.Instance | BindingFlags.Public BindingFlags.Instance | BindingFlags.Public
); );
private static readonly MethodInfo NativeSingleTrackQueryExecutorTrackAsync //对象查询追踪方法
= typeof(NativeSingleTrackQueryExecutor) private static readonly MethodInfo TrackAsync
= typeof(NativeTrackQueryExecutor)
.GetMethod( .GetMethod(
nameof(NativeSingleTrackQueryExecutor.TrackAsync), nameof(NativeTrackQueryExecutor.TrackAsync),
BindingFlags.Instance | BindingFlags.Public BindingFlags.Instance | BindingFlags.Public
); );
private static readonly MethodInfo NativeEnumeratorTrackQueryExecutorTrack //列表查询追踪方法
= typeof(NativeEnumeratorTrackQueryExecutor) private static readonly MethodInfo TrackEnumerable
= typeof(NativeTrackQueryExecutor)
.GetMethod( .GetMethod(
nameof(NativeEnumeratorTrackQueryExecutor.Track), nameof(NativeTrackQueryExecutor.TrackEnumerable),
BindingFlags.Instance | BindingFlags.Public BindingFlags.Instance | BindingFlags.Public
); );
private static readonly MethodInfo NativeEnumeratorTrackQueryExecutorTrackAsync //列表查询追踪方法
= typeof(NativeEnumeratorTrackQueryExecutor) private static readonly MethodInfo TrackAsyncEnumerable
= typeof(NativeTrackQueryExecutor)
.GetMethod( .GetMethod(
nameof(NativeEnumeratorTrackQueryExecutor.TrackAsync), nameof(NativeTrackQueryExecutor.TrackAsyncEnumerable),
BindingFlags.Instance | BindingFlags.Public BindingFlags.Instance | BindingFlags.Public
); );
private readonly IShardingQueryExecutor _shardingQueryExecutor; private readonly IShardingQueryExecutor _shardingQueryExecutor;
private readonly INativeEnumeratorTrackQueryExecutor _nativeEnumeratorTrackQueryExecutor; private readonly INativeTrackQueryExecutor _nativeTrackQueryExecutor;
private readonly INativeSingleTrackQueryExecutor _nativeSingleTrackQueryExecutor;
public DefaultShardingTrackQueryExecutor(IShardingQueryExecutor shardingQueryExecutor, INativeEnumeratorTrackQueryExecutor nativeEnumeratorTrackQueryExecutor,INativeSingleTrackQueryExecutor nativeSingleTrackQueryExecutor) public DefaultShardingTrackQueryExecutor(IShardingQueryExecutor shardingQueryExecutor, INativeTrackQueryExecutor nativeTrackQueryExecutor)
{ {
_shardingQueryExecutor = shardingQueryExecutor; _shardingQueryExecutor = shardingQueryExecutor;
_nativeEnumeratorTrackQueryExecutor = nativeEnumeratorTrackQueryExecutor; _nativeTrackQueryExecutor = nativeTrackQueryExecutor;
_nativeSingleTrackQueryExecutor = nativeSingleTrackQueryExecutor;
} }
public TResult Execute<TResult>(IQueryCompilerContext queryCompilerContext) public TResult Execute<TResult>(IQueryCompilerContext queryCompilerContext)
{ {
@ -64,7 +66,16 @@ namespace ShardingCore.Sharding.ShardingExecutors
throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint()); throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint());
} }
//native query
var result = queryCompilerExecutor.GetQueryCompiler().Execute<TResult>(queryCompilerExecutor.GetReplaceQueryExpression()); 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 //native query
if (queryCompilerContext.IsParallelQuery() && queryCompilerContext.IsQueryTrack()) if (queryCompilerContext.IsParallelQuery() && queryCompilerContext.IsQueryTrack())
{ {
@ -77,28 +88,27 @@ namespace ShardingCore.Sharding.ShardingExecutors
{ {
if (queryCompilerContext.IsEnumerableQuery()) if (queryCompilerContext.IsEnumerableQuery())
{ {
return NativeExecute(_nativeEnumeratorTrackQueryExecutor, NativeEnumeratorTrackQueryExecutorTrack, return DoResultTrackExecute(enumerableMethod,
queryCompilerContext, queryEntityType, result); queryCompilerContext, queryEntityType, result);
} }
else if (queryCompilerContext.IsEntityQuery()) else if (queryCompilerContext.IsEntityQuery())
{ {
return NativeExecute(_nativeSingleTrackQueryExecutor, NativeSingleTrackQueryExecutorTrack, return DoResultTrackExecute(entityMethod,
queryCompilerContext, queryEntityType, result); queryCompilerContext, queryEntityType, result);
} }
} }
return result; return 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) IQueryCompilerContext queryCompilerContext,Type queryEntityType, TResult result)
{ {
return (TResult)executorMethod return (TResult)executorMethod
.MakeGenericMethod(queryEntityType) .MakeGenericMethod(queryEntityType)
.Invoke(executor, new object[] { queryCompilerContext, result }); .Invoke(_nativeTrackQueryExecutor, new object[] { queryCompilerContext, result });
} }
#if !EFCORE2 #if !EFCORE2
@ -113,34 +123,14 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _shardingQueryExecutor.ExecuteAsync<TResult>(mergeQueryCompilerContext); return _shardingQueryExecutor.ExecuteAsync<TResult>(mergeQueryCompilerContext);
} }
throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint()); throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint());
} }
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression(), cancellationToken);
//native query //native query
if (queryCompilerContext.IsParallelQuery()&&queryCompilerContext.IsQueryTrack()) var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression(), cancellationToken);
{
var queryEntityType = queryCompilerContext.GetQueryableEntityType(); //native query track
var trackerManager = return ResultTrackExecute(result, queryCompilerContext, TrackAsyncEnumerable, TrackAsync);
(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;
} }
#endif #endif
#if EFCORE2 #if EFCORE2
@ -156,31 +146,11 @@ namespace ShardingCore.Sharding.ShardingExecutors
} }
throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint()); throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint());
} }
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression());
//native query //native query
if (queryCompilerContext.IsParallelQuery()&&queryCompilerContext.IsQueryTrack()) var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression());
{
var queryEntityType = queryCompilerContext.GetQueryableEntityType(); //native query track
var trackerManager = return ResultTrackExecute(result, queryCompilerContext, TrackAsyncEnumerable, Track);
(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;
} }
public Task<TResult> ExecuteAsync<TResult>(IQueryCompilerContext queryCompilerContext, CancellationToken cancellationToken) public Task<TResult> ExecuteAsync<TResult>(IQueryCompilerContext queryCompilerContext, CancellationToken cancellationToken)
@ -194,31 +164,11 @@ namespace ShardingCore.Sharding.ShardingExecutors
} }
throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint()); throw new ShardingCoreNotFoundException(queryCompilerContext.GetQueryExpression().ShardingPrint());
} }
var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression(), cancellationToken);
//native query //native query
if (queryCompilerContext.IsParallelQuery()&&queryCompilerContext.IsQueryTrack()) var result = queryCompilerExecutor.GetQueryCompiler().ExecuteAsync<TResult>(queryCompilerExecutor.GetReplaceQueryExpression(), cancellationToken);
{
var queryEntityType = queryCompilerContext.GetQueryableEntityType(); //native query track
var trackerManager = return ResultTrackExecute(result, queryCompilerContext, TrackEnumerable, TrackAsync);
(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;
} }
#endif #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 namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries
{ {
public interface INativeSingleTrackQueryExecutor public interface INativeTrackQueryExecutor
{ {
TResult Track<TResult>(IQueryCompilerContext queryCompilerContext, TResult resultTask); TResult Track<TResult>(IQueryCompilerContext queryCompilerContext, TResult resultTask);
Task<TResult> TrackAsync<TResult>(IQueryCompilerContext queryCompilerContext, Task<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.QueryTrackers;
using ShardingCore.Core.TrackerManagers; using ShardingCore.Core.TrackerManagers;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators.TrackerEnumerables;
using ShardingCore.Sharding.ShardingExecutors.Abstractions; using ShardingCore.Sharding.ShardingExecutors.Abstractions;
namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries
{ {
public class NativeSingleTrackQueryExecutor: INativeSingleTrackQueryExecutor public class NativeTrackQueryExecutor : INativeTrackQueryExecutor
{ {
private readonly IQueryTracker _queryTracker; private readonly IQueryTracker _queryTracker;
public NativeSingleTrackQueryExecutor(IQueryTracker queryTracker) public NativeTrackQueryExecutor(IQueryTracker queryTracker)
{ {
_queryTracker = queryTracker; _queryTracker = queryTracker;
} }
@ -41,6 +42,16 @@ namespace ShardingCore.Sharding.ShardingExecutors.NativeTrackQueries
var result = await resultTask; var result = await resultTask;
return Track(queryCompilerContext, result); 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> /// </summary>
private readonly bool _shardingTableRoute; private readonly bool _shardingTableRoute;
private Expression<Func<string, bool>> _where = x => true; private Expression<Func<string, bool>> _where = x => true;
private bool useQueryFilterOnFirstWhere = false;
private readonly ShardingPredicateResult _noShardingPredicateResult = new ShardingPredicateResult(false, null); private readonly ShardingPredicateResult _noShardingPredicateResult = new ShardingPredicateResult(false, null);
@ -46,6 +47,15 @@ namespace ShardingCore.Core.Internal.Visitors
public Expression<Func<string, bool>> GetRouteParseExpression() 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; return _where;
} }
@ -59,13 +69,13 @@ namespace ShardingCore.Core.Internal.Visitors
var isShardingKey = false; var isShardingKey = false;
if (_shardingTableRoute) if (_shardingTableRoute)
{ {
isShardingKey = _entityMetadata.ShardingTableProperties.ContainsKey(member.Member.Name); isShardingKey = _entityMetadata.ShardingTableProperties.ContainsKey(member.Member.Name);
} }
else else
{ {
isShardingKey = _entityMetadata.ShardingDataSourceProperties.ContainsKey(member.Member.Name); 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) if (unaryExpression.Operand is LambdaExpression lambdaExpression)
{ {
var newWhere = Resolve(lambdaExpression); var newWhere = DoResolve(lambdaExpression);
_where = _where.And(newWhere); _where = _where.And(newWhere);
} }
} }
@ -177,6 +187,22 @@ namespace ShardingCore.Core.Internal.Visitors
return base.VisitMethodCall(node); 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) private Expression<Func<string, bool>> Resolve(Expression expression)
{ {

View File

@ -428,6 +428,11 @@ namespace ShardingCore.Test
var list3 = await queryable1.ToListAsync(); var list3 = await queryable1.ToListAsync();
Assert.Equal(1, list3.Count()); Assert.Equal(1, list3.Count());
Assert.Contains(list3, o => o.Name == "name_300"); 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] [Fact]

View File

@ -400,6 +400,11 @@ namespace ShardingCore.Test2x
var list3 = await queryable1.ToListAsync(); var list3 = await queryable1.ToListAsync();
Assert.Equal(1, list3.Count()); Assert.Equal(1, list3.Count());
Assert.Contains(list3, o => o.Name == "name_300"); 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] [Fact]

View File

@ -399,6 +399,11 @@ namespace ShardingCore.Test3x
var list3 = await queryable1.ToListAsync(); var list3 = await queryable1.ToListAsync();
Assert.Equal(1, list3.Count()); Assert.Equal(1, list3.Count());
Assert.Contains(list3, o => o.Name == "name_300"); 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] [Fact]

View File

@ -399,6 +399,11 @@ namespace ShardingCore.Test5x
var list3 = await queryable1.ToListAsync(); var list3 = await queryable1.ToListAsync();
Assert.Equal(1, list3.Count()); Assert.Equal(1, list3.Count());
Assert.Contains(list3, o => o.Name == "name_300"); 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] [Fact]