提交首次将first or default修改

This commit is contained in:
xuejiaming 2022-07-03 22:26:31 +08:00
parent 89a8e66a6f
commit bba0bb9284
21 changed files with 262 additions and 327 deletions

View File

@ -26,6 +26,8 @@ namespace Sample.MySql.Controllers
[HttpGet] [HttpGet]
public async Task<IActionResult> Get() public async Task<IActionResult> Get()
{ {
var resultX = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "2" || o.Id == "3").FirstOrDefaultAsync();
var resultY = await _defaultTableDbContext.Set<SysUserMod>().FirstOrDefaultAsync(o => o.Id == "2" || o.Id == "3");
var result = await _defaultTableDbContext.Set<SysTest>().AnyAsync(); var result = await _defaultTableDbContext.Set<SysTest>().AnyAsync();
var result1 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "2" || o.Id == "3").ToListAsync(); var result1 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "2" || o.Id == "3").ToListAsync();
var result2 = await _defaultTableDbContext.Set<SysUserLogByMonth>().Skip(1).Take(10).ToListAsync(); var result2 = await _defaultTableDbContext.Set<SysUserLogByMonth>().Skip(1).Take(10).ToListAsync();

View File

@ -7,6 +7,8 @@ using ShardingCore.Bootstrappers;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.RuntimeContexts; using ShardingCore.Core.RuntimeContexts;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.TableExists;
using ShardingCore.TableExists.Abstractions;
namespace Sample.MySql namespace Sample.MySql
{ {
@ -59,7 +61,7 @@ namespace Sample.MySql
builder.UseMySql(connection, new MySqlServerVersion(new Version())).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(efLogger); builder.UseMySql(connection, new MySqlServerVersion(new Version())).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(efLogger);
}); });
o.AddDefaultDataSource("ds0", "server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;"); o.AddDefaultDataSource("ds0", "server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;");
}) }).ReplaceService<ITableEnsureManager,MySqlTableEnsureManager>(ServiceLifetime.Singleton)
.Build(sp); .Build(sp);
stopwatch.Stop(); stopwatch.Stop();
Console.WriteLine("ShardingRuntimeContext build:"+stopwatch.ElapsedMilliseconds); Console.WriteLine("ShardingRuntimeContext build:"+stopwatch.ElapsedMilliseconds);

View File

@ -27,14 +27,6 @@ namespace ShardingCore.Extensions
private static readonly MethodInfo QueryableTakeMethod = typeof(Queryable).GetMethods().First( private static readonly MethodInfo QueryableTakeMethod = typeof(Queryable).GetMethods().First(
m => m.Name == nameof(Queryable.Take) m => m.Name == nameof(Queryable.Take)
&& m.GetParameters().Length == 2 && m.GetParameters()[1].ParameterType == typeof(int)); && m.GetParameters().Length == 2 && m.GetParameters()[1].ParameterType == typeof(int));
internal static ExtraEntry GetExtraEntry<T>(this IQueryable<T> source)
{
var extraVisitor = new QueryableExtraDiscoverVisitor();
extraVisitor.Visit(source.Expression);
var extraEntry = new ExtraEntry(extraVisitor.GetPaginationContext().Skip, extraVisitor.GetPaginationContext().Take, extraVisitor.GetOrderByContext().PropertyOrders,extraVisitor.GetSelectContext(),extraVisitor.GetGroupByContext());
extraEntry.ProcessGroupBySelectProperties();
return extraEntry;
}
/// <summary> /// <summary>
/// 删除Skip表达式 /// 删除Skip表达式
/// </summary> /// </summary>

View File

@ -0,0 +1,13 @@
using System.Linq;
namespace ShardingCore.Sharding.Abstractions
{
public interface IMergeContext
{
IQueryable GetCombineQueryable();
IQueryable GetRewriteQueryable();
int? GetSkip();
int? GetTake();
}
}

View File

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ShardingCore.Core.Internal.StreamMerge;
using ShardingCore.Extensions; using ShardingCore.Extensions;
namespace ShardingCore.Sharding.Enumerators namespace ShardingCore.Sharding.Enumerators

View File

@ -16,9 +16,9 @@ namespace ShardingCore.Sharding.MergeContexts
public IParseResult Parse(IMergeQueryCompilerContext mergeQueryCompilerContext) public IParseResult Parse(IMergeQueryCompilerContext mergeQueryCompilerContext)
{ {
var isEnumerableQuery = mergeQueryCompilerContext.IsEnumerableQuery(); var isEnumerableQuery = mergeQueryCompilerContext.IsEnumerableQuery();
string queryMethodName = isEnumerableQuery ? null : mergeQueryCompilerContext.QueryMethodName(); string queryMethodName = mergeQueryCompilerContext.GetQueryMethodName();
var combineQueryable = mergeQueryCompilerContext.GetQueryCombineResult().GetCombineQueryable(); var combineQueryable = mergeQueryCompilerContext.GetQueryCombineResult().GetCombineQueryable();
var queryableExtraDiscoverVisitor = new QueryableExtraDiscoverVisitor(); var queryableExtraDiscoverVisitor = new QueryableExtraDiscoverVisitor(mergeQueryCompilerContext);
queryableExtraDiscoverVisitor.Visit(combineQueryable.Expression); queryableExtraDiscoverVisitor.Visit(combineQueryable.Expression);
return new ParseResult(queryableExtraDiscoverVisitor.GetPaginationContext(), return new ParseResult(queryableExtraDiscoverVisitor.GetPaginationContext(),
queryableExtraDiscoverVisitor.GetOrderByContext(), queryableExtraDiscoverVisitor.GetSelectContext(), queryableExtraDiscoverVisitor.GetOrderByContext(), queryableExtraDiscoverVisitor.GetSelectContext(),

View File

@ -21,11 +21,12 @@ namespace ShardingCore.Sharding.MergeContexts
public sealed class QueryableRewriteEngine : IQueryableRewriteEngine public sealed class QueryableRewriteEngine : IQueryableRewriteEngine
{ {
private static readonly ISet<string> singleEntityMethodNames = new HashSet<string>(); private static readonly ISet<string> singleEntityMethodNames = new HashSet<string>();
private static readonly ISet<string> supportSingleEntityMethodNames = new HashSet<string>();
static QueryableRewriteEngine() static QueryableRewriteEngine()
{ {
singleEntityMethodNames.Add(nameof(Enumerable.First)); supportSingleEntityMethodNames.Add(nameof(Enumerable.First));
singleEntityMethodNames.Add(nameof(Enumerable.FirstOrDefault)); supportSingleEntityMethodNames.Add(nameof(Enumerable.FirstOrDefault));
singleEntityMethodNames.Add(nameof(Enumerable.Last)); singleEntityMethodNames.Add(nameof(Enumerable.Last));
singleEntityMethodNames.Add(nameof(Enumerable.LastOrDefault)); singleEntityMethodNames.Add(nameof(Enumerable.LastOrDefault));
singleEntityMethodNames.Add(nameof(Enumerable.Single)); singleEntityMethodNames.Add(nameof(Enumerable.Single));
@ -46,7 +47,7 @@ namespace ShardingCore.Sharding.MergeContexts
{ {
if (!mergeQueryCompilerContext.IsEnumerableQuery()) if (!mergeQueryCompilerContext.IsEnumerableQuery())
{ {
var queryMethodName = mergeQueryCompilerContext.QueryMethodName(); var queryMethodName = mergeQueryCompilerContext.GetQueryMethodName();
if (singleEntityMethodNames.Contains(queryMethodName)) if (singleEntityMethodNames.Contains(queryMethodName))
{ {
//todo 修复做兼容 //todo 修复做兼容
@ -69,17 +70,33 @@ namespace ShardingCore.Sharding.MergeContexts
reWriteQueryable = reWriteQueryable.RemoveSkip(); reWriteQueryable = reWriteQueryable.RemoveSkip();
} }
if (take.HasValue) //如果是first or default
var fixedTake = mergeQueryCompilerContext.GetFixedTake();
if (fixedTake.HasValue)
{ {
if (skip.HasValue) if (skip.HasValue)
{ {
reWriteQueryable = reWriteQueryable.ReSkip(0).ReTake(take.Value + skip.GetValueOrDefault()); reWriteQueryable = reWriteQueryable.ReSkip(0).ReTake(fixedTake.Value + skip.GetValueOrDefault());
} }
else else
{ {
reWriteQueryable = reWriteQueryable.ReTake(take.Value + skip.GetValueOrDefault()); reWriteQueryable = reWriteQueryable.ReTake(fixedTake.Value);
} }
} }
else
{
if (take.HasValue)
{
if (skip.HasValue)
{
reWriteQueryable = reWriteQueryable.ReSkip(0).ReTake(take.Value + skip.GetValueOrDefault());
}
else
{
reWriteQueryable = reWriteQueryable.ReTake(take.Value + skip.GetValueOrDefault());
}
}
}
//包含group by //包含group by
if (groupByContext.GroupExpression != null) if (groupByContext.GroupExpression != null)
{ {

View File

@ -107,7 +107,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines.Enumer
var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o => o.RouteQueryResult)).Skip(skip).Take(take).ToList(); var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o => o.RouteQueryResult)).Skip(skip).Take(take).ToList();
GetStreamMergeContext().ReSetOrders(reSetOrders); GetStreamMergeContext().ReSetOrders(reSetOrders.ToArray());
return sequenceResults.Select(sequenceResult => new SqlSequenceRouteUnit(sequenceResult)); return sequenceResults.Select(sequenceResult => new SqlSequenceRouteUnit(sequenceResult));
} }

View File

@ -1,68 +1,75 @@
// using System.Collections.Generic; using System.Collections.Generic;
// using System.Linq; using System.Linq;
// using System.Threading; using System.Threading;
// using System.Threading.Tasks; using System.Threading.Tasks;
// using ShardingCore.Extensions; using ShardingCore.Extensions;
// using ShardingCore.Sharding.MergeEngines.Abstractions.InMemoryMerge; using ShardingCore.Sharding.MergeEngines.Abstractions.InMemoryMerge;
// using ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines; using ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines;
//
// namespace ShardingCore.Sharding.MergeEngines namespace ShardingCore.Sharding.MergeEngines
// { {
// /* /*
// * @Author: xjm * @Author: xjm
// * @Description: * @Description:
// * @Date: 2021/8/17 15:16:36 * @Date: 2021/8/17 15:16:36
// * @Ver: 1.0 * @Ver: 1.0
// * @Email: 326308290@qq.com * @Email: 326308290@qq.com
// */ */
// internal class FirstOrDefaultSkipAsyncInMemoryMergeEngine<TEntity> : IEnsureMergeResult<TEntity> internal class FirstOrDefaultSkipAsyncInMemoryMergeEngine<TEntity> : IEnsureMergeResult<TEntity>
// { {
// private readonly StreamMergeContext _streamMergeContext; private readonly StreamMergeContext _streamMergeContext;
//
// public FirstOrDefaultSkipAsyncInMemoryMergeEngine(StreamMergeContext streamMergeContext) public FirstOrDefaultSkipAsyncInMemoryMergeEngine(StreamMergeContext streamMergeContext)
// { {
// _streamMergeContext = streamMergeContext; _streamMergeContext = streamMergeContext;
// } }
// // protected override IExecutor<RouteQueryResult<TEntity>> CreateExecutor0(bool async)
// // { // protected override IExecutor<RouteQueryResult<TEntity>> CreateExecutor0(bool async)
// // return new FirstOrDefaultMethodExecutor<TEntity>(GetStreamMergeContext()); // {
// // } // return new FirstOrDefaultMethodExecutor<TEntity>(GetStreamMergeContext());
// // // }
// // protected override TEntity DoMergeResult0(List<RouteQueryResult<TEntity>> resultList) //
// // { // protected override TEntity DoMergeResult0(List<RouteQueryResult<TEntity>> resultList)
// // var notNullResult = resultList.Where(o => o != null && o.HasQueryResult()).Select(o => o.QueryResult).ToList(); // {
// // // var notNullResult = resultList.Where(o => o != null && o.HasQueryResult()).Select(o => o.QueryResult).ToList();
// // if (notNullResult.IsEmpty()) //
// // return default; // if (notNullResult.IsEmpty())
// // // return default;
// // var streamMergeContext = GetStreamMergeContext(); //
// // if (streamMergeContext.Orders.Any()) // var streamMergeContext = GetStreamMergeContext();
// // return notNullResult.AsQueryable().OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).FirstOrDefault(); // if (streamMergeContext.Orders.Any())
// // // return notNullResult.AsQueryable().OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).FirstOrDefault();
// // return notNullResult.FirstOrDefault(); //
// // } // return notNullResult.FirstOrDefault();
// public TEntity MergeResult() // }
// { public TEntity MergeResult()
// return MergeResultAsync().WaitAndUnwrapException(false); {
// } return MergeResultAsync().WaitAndUnwrapException(false);
// }
// public async Task<TEntity> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
// { public async Task<TEntity> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
// {
// //将toke改成1 //将toke改成1
// var asyncEnumeratorStreamMergeEngine = new AsyncEnumeratorStreamMergeEngine<TEntity>(_streamMergeContext); var asyncEnumeratorStreamMergeEngine = new AsyncEnumeratorStreamMergeEngine<TEntity>(_streamMergeContext);
//
// var list = new List<TEntity>(); #if EFCORE2
// await foreach (var element in asyncEnumeratorStreamMergeEngine.WithCancellation(cancellationToken)) var list = await asyncEnumeratorStreamMergeEngine.ToList<TEntity>(cancellationToken);
// { #endif
// list.Add(element); #if !EFCORE2
// } var take = _streamMergeContext.GetTake();
// var list = new List<TEntity>(take??31);
// if (list.IsEmpty()) await foreach (var element in asyncEnumeratorStreamMergeEngine.WithCancellation(cancellationToken))
// { {
// return default; list.Add(element);
// } }
// return list.FirstOrDefault(); #endif
// }
// } if (list.IsEmpty())
// } {
return default;
}
return list.FirstOrDefault();
}
}
}

View File

@ -1,73 +1,78 @@
// using System; using System;
// using System.Collections.Generic; using System.Collections.Generic;
// using System.Linq; using System.Linq;
// using System.Threading; using System.Threading;
// using System.Threading.Tasks; using System.Threading.Tasks;
// using ShardingCore.Extensions; using ShardingCore.Extensions;
// using ShardingCore.Sharding.MergeEngines.Abstractions.InMemoryMerge; using ShardingCore.Sharding.MergeEngines.Abstractions.InMemoryMerge;
// using ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines; using ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines;
//
// namespace ShardingCore.Sharding.MergeEngines namespace ShardingCore.Sharding.MergeEngines
// { {
//
// public class FirstSkipAsyncInMemoryMergeEngine<TEntity> : IEnsureMergeResult<TEntity> public class FirstSkipAsyncInMemoryMergeEngine<TEntity> : IEnsureMergeResult<TEntity>
// { {
// private readonly StreamMergeContext _streamMergeContext; private readonly StreamMergeContext _streamMergeContext;
//
// public FirstSkipAsyncInMemoryMergeEngine(StreamMergeContext streamMergeContext) public FirstSkipAsyncInMemoryMergeEngine(StreamMergeContext streamMergeContext)
// { {
// _streamMergeContext = streamMergeContext; _streamMergeContext = streamMergeContext;
// } }
// // protected override IExecutor<RouteQueryResult<TEntity>> CreateExecutor0(bool async) // protected override IExecutor<RouteQueryResult<TEntity>> CreateExecutor0(bool async)
// // { // {
// // return new FirstOrDefaultMethodExecutor<TEntity>(GetStreamMergeContext()); // return new FirstOrDefaultMethodExecutor<TEntity>(GetStreamMergeContext());
// // } // }
// // //
// // protected override TEntity DoMergeResult0(List<RouteQueryResult<TEntity>> resultList) // protected override TEntity DoMergeResult0(List<RouteQueryResult<TEntity>> resultList)
// // { // {
// // var notNullResult = resultList.Where(o => o != null && o.HasQueryResult()).Select(o => o.QueryResult).ToList(); // var notNullResult = resultList.Where(o => o != null && o.HasQueryResult()).Select(o => o.QueryResult).ToList();
// // //
// // if (notNullResult.IsEmpty()) // if (notNullResult.IsEmpty())
// // return default; // return default;
// // //
// // var streamMergeContext = GetStreamMergeContext(); // var streamMergeContext = GetStreamMergeContext();
// // if (streamMergeContext.Orders.Any()) // if (streamMergeContext.Orders.Any())
// // return notNullResult.AsQueryable().OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).FirstOrDefault(); // return notNullResult.AsQueryable().OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).FirstOrDefault();
// // //
// // return notNullResult.FirstOrDefault(); // return notNullResult.FirstOrDefault();
// // } // }
// public TEntity MergeResult() public TEntity MergeResult()
// { {
// return MergeResultAsync().WaitAndUnwrapException(false); return MergeResultAsync().WaitAndUnwrapException(false);
// } }
//
// public async Task<TEntity> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) public async Task<TEntity> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
// { {
//
// //将toke改成1 //将toke改成1
// var asyncEnumeratorStreamMergeEngine = new AsyncEnumeratorStreamMergeEngine<TEntity>(_streamMergeContext); var asyncEnumeratorStreamMergeEngine = new AsyncEnumeratorStreamMergeEngine<TEntity>(_streamMergeContext);
//
// var list = new List<TEntity>(); #if EFCORE2
// await foreach (var element in asyncEnumeratorStreamMergeEngine.WithCancellation(cancellationToken)) var list = await asyncEnumeratorStreamMergeEngine.ToList<TEntity>(cancellationToken);
// { #endif
// list.Add(element); #if !EFCORE2
// } var take = _streamMergeContext.GetTake();
// var list = new List<TEntity>(take??31);
// if (list.IsEmpty()) await foreach (var element in asyncEnumeratorStreamMergeEngine.WithCancellation(cancellationToken))
// throw new InvalidOperationException("Sequence contains no elements."); {
// list.Add(element);
// return list.First(); }
// } #endif
// if (list.IsEmpty())
// throw new InvalidOperationException("Sequence contains no elements.");
// // if (notNullResult.IsEmpty())
// // throw new InvalidOperationException("Sequence contains no elements."); return list.First();
// // }
// // var streamMergeContext = GetStreamMergeContext();
// // if (streamMergeContext.Orders.Any())
// // return notNullResult.AsQueryable().OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).First(); // if (notNullResult.IsEmpty())
// // // throw new InvalidOperationException("Sequence contains no elements.");
// // return notNullResult.First(); //
// } // var streamMergeContext = GetStreamMergeContext();
// } // if (streamMergeContext.Orders.Any())
// // return notNullResult.AsQueryable().OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).First();
//
// return notNullResult.First();
}
}

View File

@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Sharding.MergeContexts;
using ShardingCore.Sharding.Visitors.Selects;
namespace ShardingCore.Core.Internal.StreamMerge.ReWrite
{
/*
* @Author: xjm
* @Description:
* @Date: Thursday, 28 January 2021 23:44:24
* @Email: 326308290@qq.com
*/
internal class ReWriteEngine<T>
{
private readonly IQueryable<T> _queryable;
public ReWriteEngine(IQueryable<T> queryable)
{
_queryable = queryable;
}
public ReWriteResult<T> ReWrite()
{
var extraEntry = _queryable.GetExtraEntry();
var skip = extraEntry.Skip;
var take = extraEntry.Take;
var orders = extraEntry.Orders ?? Enumerable.Empty<PropertyOrder>();
//去除分页,获取前Take+Skip数量
var reWriteQueryable = _queryable;
if (take.HasValue)
{
reWriteQueryable = reWriteQueryable.RemoveTake().As<IQueryable<T>>();
}
if (skip.HasValue)
{
reWriteQueryable = reWriteQueryable.RemoveSkip().As<IQueryable<T>>();
}
if (take.HasValue)
{
if (skip.HasValue)
{
reWriteQueryable = reWriteQueryable.Skip(0).Take(take.Value + skip.GetValueOrDefault());
}
else
{
reWriteQueryable = reWriteQueryable.Take(take.Value + skip.GetValueOrDefault());
}
}
//包含group by
if (extraEntry.GroupByContext.GroupExpression != null)
{
if (orders.IsEmpty())
{
//将查询的属性转换成order by
var selectProperties = extraEntry.SelectContext.SelectProperties.Where(o => !(o is SelectAggregateProperty));
if (selectProperties.IsNotEmpty())
{
var sort = string.Join(",",selectProperties.Select(o=>$"{o.PropertyName} asc"));
reWriteQueryable = reWriteQueryable.OrderWithExpression(sort,null);
var reWriteOrders = new List<PropertyOrder>(selectProperties.Count());
foreach (var orderProperty in selectProperties)
{
reWriteOrders.Add(new PropertyOrder(orderProperty.PropertyName,true, orderProperty.OwnerType));
}
orders = reWriteOrders;
}
}
else
{
//将查询的属性转换成order by 并且order和select的未聚合查询必须一致
var selectProperties = extraEntry.SelectContext.SelectProperties.Where(o => !(o is SelectAggregateProperty));
if (orders.Count() != selectProperties.Count())
throw new ShardingCoreInvalidOperationException("group by query order items not equal select un-aggregate items");
var os=orders.Select(o => o.PropertyExpression).ToList();
var ss = selectProperties.Select(o => o.PropertyName).ToList();
for (int i = 0; i < os.Count(); i++)
{
if(!os[i].Equals(ss[i]))
throw new ShardingCoreInvalidOperationException($"group by query order items not equal select un-aggregate items: order:[{os[i]}],select:[{ss[i]}");
}
}
}
return new ReWriteResult<T>(_queryable,reWriteQueryable,skip,take,orders,extraEntry.SelectContext,extraEntry.GroupByContext);
}
}
}

View File

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Core.Internal.Visitors.Selects;
using ShardingCore.Sharding.MergeContexts;
namespace ShardingCore.Core.Internal.StreamMerge.ReWrite
{
/*
* @Author: xjm
* @Description:
* @Date: Thursday, 28 January 2021 23:45:29
* @Email: 326308290@qq.com
*/
internal class ReWriteResult<T>
{
public ReWriteResult(IQueryable<T> originalQueryable, IQueryable<T> reWriteQueryable, int? skip, int? take, IEnumerable<PropertyOrder> orders, SelectContext selectContext, GroupByContext groupByContext)
{
OriginalQueryable = originalQueryable;
ReWriteQueryable = reWriteQueryable;
Skip = skip;
Take = take;
Orders = orders;
SelectContext = selectContext;
GroupByContext = groupByContext;
}
public IQueryable<T> OriginalQueryable { get; }
public IQueryable<T> ReWriteQueryable { get; }
public int? Skip { get; }
public int? Take { get; }
public IEnumerable<PropertyOrder> Orders { get; }
public SelectContext SelectContext { get; }
public GroupByContext GroupByContext { get; }
}
}

View File

@ -18,8 +18,6 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
bool IsCrossTable(); bool IsCrossTable();
bool IsCrossDataSource(); bool IsCrossDataSource();
int? GetFixedTake();
string QueryMethodName();
//bool IsEnumerableQuery();
} }
} }

View File

@ -30,6 +30,7 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
/// <returns></returns> /// <returns></returns>
QueryCompilerExecutor GetQueryCompilerExecutor(); QueryCompilerExecutor GetQueryCompilerExecutor();
bool IsEnumerableQuery(); bool IsEnumerableQuery();
string GetQueryMethodName();
/// <summary> /// <summary>
/// 当前是否读写分离走读库(包括是否启用读写分离和是否当前的dbcontext启用了读库查询) /// 当前是否读写分离走读库(包括是否启用读写分离和是否当前的dbcontext启用了读库查询)

View File

@ -15,6 +15,7 @@ using Microsoft.Extensions.Logging;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Extensions.InternalExtensions; using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Logger; using ShardingCore.Logger;
using ShardingCore.Sharding.MergeEngines;
#if EFCORE2 #if EFCORE2
using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Internal;
#endif #endif
@ -70,13 +71,13 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors
} }
private TResult DoExecute<TResult>(IMergeQueryCompilerContext mergeQueryCompilerContext, bool async, CancellationToken cancellationToken = new CancellationToken()) private TResult DoExecute<TResult>(IMergeQueryCompilerContext mergeQueryCompilerContext, bool async, CancellationToken cancellationToken = new CancellationToken())
{ {
var queryMethodName = mergeQueryCompilerContext.QueryMethodName(); var queryMethodName = mergeQueryCompilerContext.GetQueryMethodName();
switch (queryMethodName) switch (queryMethodName)
{ {
case nameof(Enumerable.First): case nameof(Enumerable.First):
return EnsureResultTypeMergeExecute<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), mergeQueryCompilerContext, async, cancellationToken); return EnsureResultTypeMergeExecute<TResult>(typeof(FirstSkipAsyncInMemoryMergeEngine<>), mergeQueryCompilerContext, async, cancellationToken);
case nameof(Enumerable.FirstOrDefault): case nameof(Enumerable.FirstOrDefault):
return EnsureResultTypeMergeExecute<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), mergeQueryCompilerContext, async, cancellationToken); return EnsureResultTypeMergeExecute<TResult>(typeof(FirstOrDefaultSkipAsyncInMemoryMergeEngine<>), mergeQueryCompilerContext, async, cancellationToken);
case nameof(Enumerable.Last): case nameof(Enumerable.Last):
return EnsureResultTypeMergeExecute<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), mergeQueryCompilerContext, async, cancellationToken); return EnsureResultTypeMergeExecute<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), mergeQueryCompilerContext, async, cancellationToken);
case nameof(Enumerable.LastOrDefault): case nameof(Enumerable.LastOrDefault):

View File

@ -49,6 +49,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
private QueryCompilerExecutor _queryCompilerExecutor; private QueryCompilerExecutor _queryCompilerExecutor;
private bool? hasQueryCompilerExecutor; private bool? hasQueryCompilerExecutor;
private readonly int? _fixedTake;
private MergeQueryCompilerContext(IShardingRuntimeContext shardingRuntimeContext,IQueryCompilerContext queryCompilerContext, QueryCombineResult queryCombineResult, ShardingRouteResult shardingRouteResult) private MergeQueryCompilerContext(IShardingRuntimeContext shardingRuntimeContext,IQueryCompilerContext queryCompilerContext, QueryCombineResult queryCombineResult, ShardingRouteResult shardingRouteResult)
{ {
_shardingRuntimeContext = shardingRuntimeContext; _shardingRuntimeContext = shardingRuntimeContext;
@ -60,6 +61,11 @@ namespace ShardingCore.Sharding.ShardingExecutors
_isCrossDataSource = shardingRouteResult.IsCrossDataSource; _isCrossDataSource = shardingRouteResult.IsCrossDataSource;
_isCrossTable = shardingRouteResult.IsCrossTable; _isCrossTable = shardingRouteResult.IsCrossTable;
_existCrossTableTails = shardingRouteResult.ExistCrossTableTails; _existCrossTableTails = shardingRouteResult.ExistCrossTableTails;
var queryMethodName = queryCompilerContext.GetQueryMethodName();
if (nameof(Enumerable.First) == queryMethodName || nameof(Enumerable.FirstOrDefault) == queryMethodName)
{
_fixedTake = 1;
}
} }
// //
// private IEnumerable<TableRouteResult> GetTableRouteResults(IEnumerable<TableRouteResult> tableRouteResults) // private IEnumerable<TableRouteResult> GetTableRouteResults(IEnumerable<TableRouteResult> tableRouteResults)
@ -208,6 +214,11 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _queryCompilerContext.IsEnumerableQuery(); return _queryCompilerContext.IsEnumerableQuery();
} }
public string GetQueryMethodName()
{
return _queryCompilerContext.GetQueryMethodName();
}
/// <summary> /// <summary>
/// 如果需要聚合并且存在跨tail的查询或者本次是读链接 /// 如果需要聚合并且存在跨tail的查询或者本次是读链接
/// </summary> /// </summary>
@ -217,23 +228,9 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _isCrossTable || _existCrossTableTails|| _queryCompilerContext.IsParallelQuery(); return _isCrossTable || _existCrossTableTails|| _queryCompilerContext.IsParallelQuery();
} }
public string QueryMethodName() public int? GetFixedTake()
{ {
if (IsEnumerableQuery()) return _fixedTake;
{
throw new ShardingCoreInvalidOperationException(
$"queryable:[{GetQueryExpression().ShardingPrint()}] is enumerable query cant found query method name");
}
if (GetQueryExpression() is MethodCallExpression methodCallExpression)
{
return methodCallExpression.Method.Name;
}
else
{
throw new ShardingCoreInvalidOperationException(
$"queryable:[{GetQueryExpression().ShardingPrint()}] not {nameof(MethodCallExpression)} cant found query method name");
}
} }
} }
} }

View File

@ -11,6 +11,7 @@ using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.RuntimeContexts; using ShardingCore.Core.RuntimeContexts;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.Parsers; using ShardingCore.Sharding.Parsers;
using ShardingCore.Sharding.Parsers.Abstractions; using ShardingCore.Sharding.Parsers.Abstractions;
@ -18,6 +19,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
{ {
public class QueryCompilerContext: IQueryCompilerContext public class QueryCompilerContext: IQueryCompilerContext
{ {
public const string ENUMERABLE = "Enumerable";
private readonly Dictionary<Type/* 查询对象类型 */, IQueryable/* 查询对象对应的表达式 */> _queryEntities; private readonly Dictionary<Type/* 查询对象类型 */, IQueryable/* 查询对象对应的表达式 */> _queryEntities;
private readonly IShardingDbContext _shardingDbContext; private readonly IShardingDbContext _shardingDbContext;
private readonly IShardingRuntimeContext _shardingRuntimeContext; private readonly IShardingRuntimeContext _shardingRuntimeContext;
@ -33,6 +35,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
private readonly ConnectionModeEnum? _connectionMode; private readonly ConnectionModeEnum? _connectionMode;
private readonly bool? _isSequence; private readonly bool? _isSequence;
private readonly bool? _sameWithShardingComparer; private readonly bool? _sameWithShardingComparer;
private readonly string _queryMethodName;
private QueryCompilerContext(IPrepareParseResult prepareParseResult) private QueryCompilerContext(IPrepareParseResult prepareParseResult)
{ {
@ -47,13 +50,32 @@ namespace ShardingCore.Sharding.ShardingExecutors
_maxQueryConnectionsLimit = prepareParseResult.GetMaxQueryConnectionsLimit(); _maxQueryConnectionsLimit = prepareParseResult.GetMaxQueryConnectionsLimit();
_connectionMode = prepareParseResult.GetConnectionMode(); _connectionMode = prepareParseResult.GetConnectionMode();
_entityMetadataManager = _shardingRuntimeContext.GetEntityMetadataManager(); _entityMetadataManager = _shardingRuntimeContext.GetEntityMetadataManager();
_queryMethodName = QueryMethodName(_queryExpression);
//原生对象的原生查询如果是读写分离就需要启用并行查询 //原生对象的原生查询如果是读写分离就需要启用并行查询
_isParallelQuery = prepareParseResult.ReadOnly().GetValueOrDefault(); _isParallelQuery = prepareParseResult.ReadOnly().GetValueOrDefault();
_isSequence = prepareParseResult.IsSequence(); _isSequence = prepareParseResult.IsSequence();
_sameWithShardingComparer = prepareParseResult.SameWithShardingComparer(); _sameWithShardingComparer = prepareParseResult.SameWithShardingComparer();
} }
private string QueryMethodName(Expression queryExpression)
{
var isEnumerableQuery = queryExpression.Type
.HasImplementedRawGeneric(typeof(IQueryable<>));
if (isEnumerableQuery)
{
return ENUMERABLE;
}
if (queryExpression is MethodCallExpression methodCallExpression)
{
return methodCallExpression.Method.Name;
}
else
{
throw new ShardingCoreInvalidOperationException(
$"queryable:[{queryExpression.ShardingPrint()}] not {nameof(MethodCallExpression)} cant found query method name");
}
}
public static QueryCompilerContext Create(IPrepareParseResult prepareParseResult) public static QueryCompilerContext Create(IPrepareParseResult prepareParseResult)
{ {
return new QueryCompilerContext(prepareParseResult); return new QueryCompilerContext(prepareParseResult);
@ -159,8 +181,12 @@ namespace ShardingCore.Sharding.ShardingExecutors
public bool IsEnumerableQuery() public bool IsEnumerableQuery()
{ {
return _queryExpression.Type return ENUMERABLE == _queryMethodName;
.HasImplementedRawGeneric(typeof(IQueryable<>)); }
public string GetQueryMethodName()
{
return _queryMethodName;
} }
} }
} }

View File

@ -49,7 +49,7 @@ namespace ShardingCore.Sharding
public int? Skip { get; private set; } public int? Skip { get; private set; }
public int? Take { get; private set;} public int? Take { get; private set;}
public IEnumerable<PropertyOrder> Orders { get; private set; } public PropertyOrder[] Orders { get; private set; }
public SelectContext SelectContext => ParseResult.GetSelectContext(); public SelectContext SelectContext => ParseResult.GetSelectContext();
public GroupByContext GroupByContext => ParseResult.GetGroupByContext(); public GroupByContext GroupByContext => ParseResult.GetGroupByContext();
@ -105,7 +105,7 @@ namespace ShardingCore.Sharding
Take = parseResult.GetPaginationContext().Take; Take = parseResult.GetPaginationContext().Take;
} }
public void ReSetOrders(IEnumerable<PropertyOrder> orders) public void ReSetOrders(PropertyOrder[] orders)
{ {
Orders = orders; Orders = orders;
} }

View File

@ -6,6 +6,7 @@ using ShardingCore.Core.Internal.Visitors.Selects;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.MergeContexts; using ShardingCore.Sharding.MergeContexts;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
using ShardingCore.Sharding.Visitors.Selects; using ShardingCore.Sharding.Visitors.Selects;
namespace ShardingCore.Core.Internal.Visitors namespace ShardingCore.Core.Internal.Visitors
@ -18,12 +19,16 @@ namespace ShardingCore.Core.Internal.Visitors
*/ */
internal class QueryableExtraDiscoverVisitor : ShardingExpressionVisitor internal class QueryableExtraDiscoverVisitor : ShardingExpressionVisitor
{ {
private readonly IMergeQueryCompilerContext _mergeQueryCompilerContext;
private GroupByContext _groupByContext = new GroupByContext(); private GroupByContext _groupByContext = new GroupByContext();
private SelectContext _selectContext = new SelectContext(); private SelectContext _selectContext = new SelectContext();
private PaginationContext _paginationContext = new PaginationContext(); private PaginationContext _paginationContext = new PaginationContext();
private OrderByContext _orderByContext = new OrderByContext(); private OrderByContext _orderByContext = new OrderByContext();
public QueryableExtraDiscoverVisitor(IMergeQueryCompilerContext mergeQueryCompilerContext)
{
_mergeQueryCompilerContext = mergeQueryCompilerContext;
}
public SelectContext GetSelectContext() public SelectContext GetSelectContext()
{ {
return _selectContext; return _selectContext;
@ -36,6 +41,11 @@ namespace ShardingCore.Core.Internal.Visitors
public PaginationContext GetPaginationContext() public PaginationContext GetPaginationContext()
{ {
var fixedTake = _mergeQueryCompilerContext.GetFixedTake();
if (fixedTake.HasValue)
{
_paginationContext.Take = fixedTake.Value;
}
return _paginationContext; return _paginationContext;
} }
public OrderByContext GetOrderByContext() public OrderByContext GetOrderByContext()

View File

@ -24,7 +24,7 @@ namespace ShardingCore.TableExists
public override ISet<string> DoGetExistTables(DbConnection connection, string dataSourceName) public override ISet<string> DoGetExistTables(DbConnection connection, string dataSourceName)
{ {
var database = connection.Database; var database = connection.Database;
ISet<string> result = new HashSet<string>(); ISet<string> result = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
using (var dataTable = connection.GetSchema(Tables)) using (var dataTable = connection.GetSchema(Tables))
{ {
for (int i = 0; i < dataTable.Rows.Count; i++) for (int i = 0; i < dataTable.Rows.Count; i++)

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore; using System;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using ShardingCore.TableExists.Abstractions; using ShardingCore.TableExists.Abstractions;
using System.Collections.Generic; using System.Collections.Generic;
@ -17,7 +18,7 @@ namespace ShardingCore.TableExists
public override ISet<string> DoGetExistTables(DbConnection connection, string dataSourceName) public override ISet<string> DoGetExistTables(DbConnection connection, string dataSourceName)
{ {
ISet<string> result = new HashSet<string>(); ISet<string> result = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
using (var dataTable = connection.GetSchema(Tables)) using (var dataTable = connection.GetSchema(Tables))
{ {
for (int i = 0; i < dataTable.Rows.Count; i++) for (int i = 0; i < dataTable.Rows.Count; i++)