[#93]完成特殊处理的优化方式

This commit is contained in:
xuejmnet 2022-02-02 22:32:49 +08:00
parent b9d7e88408
commit f213dac38e
23 changed files with 589 additions and 107 deletions

View File

@ -14,6 +14,7 @@ using System.Threading.Tasks;
using ShardingCore;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions.ShardingQueryableExtensions;
namespace Sample.SqlServer.Controllers
{
@ -174,6 +175,19 @@ namespace Sample.SqlServer.Controllers
});
}
[HttpGet]
public async Task<IActionResult> Get2a([FromQuery] int p, [FromQuery] int s)
{
Stopwatch sp = new Stopwatch();
sp.Start();
var shardingPageResultAsync = await _defaultTableDbContext.Set<SysUserMod>().UseConnectionMode(1).OrderBy(o => o.Age).ToShardingPageAsync(p, s);
sp.Stop();
return Ok(new
{
sp.ElapsedMilliseconds,
shardingPageResultAsync
});
}
[HttpGet]
public IActionResult Get2([FromQuery] int p, [FromQuery] int s)
{
Stopwatch sp = new Stopwatch();

View File

@ -7,10 +7,8 @@ using ShardingCore.Sharding.ShardingExecutors.Abstractions;
namespace ShardingCore.Core.NotSupportShardingProviders
{
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
public interface INotSupportShardingProvider
{
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
void CheckNotSupportSharding(IQueryCompilerContext queryCompilerContext);
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext);

View File

@ -0,0 +1,24 @@
using System;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
/*
* @Author: xjm
* @Description:
* @Date: DATE TIME
* @Email: 326308290@qq.com
*/
namespace ShardingCore.Extensions
{
public static class CompileParameterExtension
{
/// <summary>
/// 是否存在自定义查询
/// </summary>
/// <param name="compileParameter"></param>
/// <returns></returns>
public static bool HasCustomerQuery(this ICompileParameter compileParameter)
{
return compileParameter.ReadOnly().HasValue || compileParameter.GetAsRoute() != null;
}
}
}

View File

@ -4,27 +4,44 @@ using System.Linq.Expressions;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Query.Internal;
using ShardingCore.Core;
using ShardingCore.Core.QueryRouteManagers;
namespace ShardingCore.Extensions.ShardingQueryableExtensions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 30 January 2022 00:12:37
* @Email: 326308290@qq.com
*/
namespace ShardingCore.Extensions.ShardingQueryableExtensions
{
/// <summary>
/// 分片查询额外扩展
/// </summary>
public static class EntityFrameworkShardingQueryableExtension
{
internal static readonly MethodInfo NotSupportMethodInfo
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(NotSupport)).Single();
internal static readonly MethodInfo AsRouteMethodInfo
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(AsRoute)).Single();
internal static readonly MethodInfo UseConfigMethodInfo
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(UseConfig)).Single();
= typeof(EntityFrameworkShardingQueryableExtension)
.GetTypeInfo()
.GetMethods(BindingFlags.Instance | BindingFlags.Static |BindingFlags.NonPublic)
.Where(m => m.Name == nameof(AsRoute))
.Single(m => m.GetParameters().Any(p => p.ParameterType == typeof(ShardingQueryableAsRouteOptions)));
internal static readonly MethodInfo UseConnectionModeMethodInfo
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(UseConnectionMode)).Single();
= typeof(EntityFrameworkShardingQueryableExtension)
.GetTypeInfo()
.GetMethods(BindingFlags.Instance | BindingFlags.Static |BindingFlags.NonPublic)
.Where(m => m.Name == nameof(UseConnectionMode))
.Single(m => m.GetParameters().Any(p => p.ParameterType == typeof(ShardingQueryableUseConnectionModeOptions)));
internal static readonly MethodInfo ReadWriteSeparationMethodInfo
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(ReadWriteSeparation)).Single();
= typeof(EntityFrameworkShardingQueryableExtension)
.GetTypeInfo()
.GetMethods()
.Where(m => m.Name == nameof(ReadWriteSeparation))
.Single(m => m.GetParameters().Any(p => p.ParameterType == typeof(bool)));
/// <summary>
/// 标记当前操作是不支持分片的可以自行才用union all
@ -45,32 +62,37 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
source.Expression))
: source;
}
/// <summary>
/// 开启提示路由的前提下手动指定表、手动指定数据源
/// </summary>
/// <param name="source"></param>
/// <param name="routeConfigure"></param>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public static IQueryable<TEntity> AsRoute<TEntity>(this IQueryable<TEntity> source,Action<ShardingQueryableAsRouteOptions> routeConfigure)
/// <summary>
/// 开启提示路由的前提下手动指定表、手动指定数据源
/// </summary>
/// <param name="source"></param>
/// <param name="routeConfigure"></param>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public static IQueryable<TEntity> AsRoute<TEntity>(this IQueryable<TEntity> source, Action<ShardingRouteContext> routeConfigure)
{
Check.NotNull(source, nameof(source));
Check.NotNull(routeConfigure, nameof(routeConfigure));
return source;
var shardingQueryableAsRouteOptions = new ShardingQueryableAsRouteOptions(routeConfigure);
return source.AsRoute(shardingQueryableAsRouteOptions);
}
/// <summary>
/// 使用哪个配置多配置下有效
/// </summary>
/// <param name="source"></param>
/// <param name="configId"></param>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public static IQueryable<TEntity> UseConfig<TEntity>(this IQueryable<TEntity> source,string configId)
internal static IQueryable<TEntity> AsRoute<TEntity>(this IQueryable<TEntity> source, ShardingQueryableAsRouteOptions shardingQueryableAsRouteOptions)
{
Check.NotNull(source, nameof(source));
Check.NotNull(configId, nameof(configId));
return source;
return
source.Provider is EntityQueryProvider
? source.Provider.CreateQuery<TEntity>(
Expression.Call(
(Expression)null,
AsRouteMethodInfo.MakeGenericMethod(typeof(TEntity)),
source.Expression,
Expression.Constant(shardingQueryableAsRouteOptions)))
: source;
}
/// <summary>
/// 设置连接而模式
/// </summary>
@ -80,13 +102,30 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static IQueryable<TEntity> UseConnectionMode<TEntity>(this IQueryable<TEntity> source,int maxQueryConnectionsLimit,ConnectionModeEnum connectionMode)
public static IQueryable<TEntity> UseConnectionMode<TEntity>(this IQueryable<TEntity> source, int maxQueryConnectionsLimit, ConnectionModeEnum connectionMode = ConnectionModeEnum.SYSTEM_AUTO)
{
Check.NotNull(source, nameof(source));
if (maxQueryConnectionsLimit <= 0)
throw new ArgumentException($"{nameof(UseConnectionMode)} {nameof(maxQueryConnectionsLimit)} should >=1");
return source;
var shardingQueryableUseConnectionModeOptions = new ShardingQueryableUseConnectionModeOptions(maxQueryConnectionsLimit, connectionMode);
return UseConnectionMode(source,shardingQueryableUseConnectionModeOptions);
}
internal static IQueryable<TEntity> UseConnectionMode<TEntity>(this IQueryable<TEntity> source, ShardingQueryableUseConnectionModeOptions shardingQueryableUseConnectionModeOptions)
{
Check.NotNull(source, nameof(source));
return
source.Provider is EntityQueryProvider
? source.Provider.CreateQuery<TEntity>(
Expression.Call(
(Expression)null,
UseConnectionModeMethodInfo.MakeGenericMethod(typeof(TEntity)),
source.Expression,
Expression.Constant(shardingQueryableUseConnectionModeOptions)))
: source;
}
/// <summary>
/// 走读库
/// </summary>
@ -97,6 +136,7 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
{
return source.ReadWriteSeparation(true);
}
/// <summary>
/// 走写库
/// </summary>
@ -107,6 +147,7 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
{
return source.ReadWriteSeparation(false);
}
/// <summary>
/// 自定义读写分离走什么库
/// </summary>
@ -114,10 +155,20 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
/// <param name="routeReadConnect"></param>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public static IQueryable<TEntity> ReadWriteSeparation<TEntity>(this IQueryable<TEntity> source,bool routeReadConnect)
public static IQueryable<TEntity> ReadWriteSeparation<TEntity>(this IQueryable<TEntity> source, bool routeReadConnect)
{
Check.NotNull(source, nameof(source));
return source;
var shardingQueryableReadWriteSeparationOptions = new ShardingQueryableReadWriteSeparationOptions(routeReadConnect);
return
source.Provider is EntityQueryProvider
? source.Provider.CreateQuery<TEntity>(
Expression.Call(
(Expression)null,
ReadWriteSeparationMethodInfo.MakeGenericMethod(typeof(TEntity)),
source.Expression,
Expression.Constant(shardingQueryableReadWriteSeparationOptions)))
: source;
}
}
}

View File

@ -10,13 +10,13 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
* @Date: Monday, 31 January 2022 00:15:37
* @Email: 326308290@qq.com
*/
public class ShardingQueryableAsRouteOptions
internal class ShardingQueryableAsRouteOptions
{
private readonly Action<ShardingRouteContext> _routeConfigure;
public Action<ShardingRouteContext> RouteConfigure { get; }
public ShardingQueryableAsRouteOptions(Action<ShardingRouteContext> routeConfigure)
{
_routeConfigure = routeConfigure;
RouteConfigure = routeConfigure;
}
}
}

View File

@ -0,0 +1,20 @@
using System;
namespace ShardingCore.Extensions.ShardingQueryableExtensions
{
/*
* @Author: xjm
* @Description:
* @Date: Tuesday, 01 February 2022 16:48:17
* @Email: 326308290@qq.com
*/
internal class ShardingQueryableReadWriteSeparationOptions
{
public bool RouteReadConnect { get; }
public ShardingQueryableReadWriteSeparationOptions(bool routeReadConnect)
{
RouteReadConnect = routeReadConnect;
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using ShardingCore.Core;
namespace ShardingCore.Extensions.ShardingQueryableExtensions
{
/*
* @Author: xjm
* @Description:
* @Date: Monday, 31 January 2022 22:51:56
* @Email: 326308290@qq.com
*/
internal class ShardingQueryableUseConnectionModeOptions
{
public ShardingQueryableUseConnectionModeOptions(int maxQueryConnectionsLimit, ConnectionModeEnum connectionMode)
{
MaxQueryConnectionsLimit = maxQueryConnectionsLimit;
ConnectionMode = connectionMode;
}
public int MaxQueryConnectionsLimit { get; }
public ConnectionModeEnum ConnectionMode { get; }
}
}

View File

@ -10,6 +10,6 @@ namespace ShardingCore.Sharding.Abstractions
{
public interface IQueryCompilerContextFactory
{
IQueryCompilerContext Create(IShardingDbContext shardingDbContext, Expression queryExpression);
IQueryCompilerContext Create(ICompileParameter compileParameter);
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Linq.Expressions;
using ShardingCore.Core;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Tuesday, 01 February 2022 22:55:23
* @Email: 326308290@qq.com
*/
public interface ICompileParameter
{
/// <summary>
/// 获取当前分片上下文
/// </summary>
/// <returns></returns>
IShardingDbContext GetShardingDbContext();
/// <summary>
/// 获取原始的查询表达式
/// </summary>
/// <returns></returns>
Expression GetNativeQueryExpression();
/// <summary>
/// 当前查询是否是支持的查询
/// </summary>
/// <returns></returns>
bool IsNotSupport();
/// <summary>
/// 当前查询的连接数限制
/// </summary>
/// <returns></returns>
int? GetMaxQueryConnectionsLimit();
/// <summary>
/// 当前查询的连接模式
/// </summary>
/// <returns></returns>
ConnectionModeEnum? GetConnectionMode();
/// <summary>
/// 在启用读写分离后如果设置了readonly那么就走readonly否则为null
/// </summary>
/// <returns></returns>
bool? ReadOnly();
/// <summary>
/// 自定义路由
/// </summary>
/// <returns></returns>
Action<ShardingRouteContext> GetAsRoute();
}
}

View File

@ -6,6 +6,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.Internal;
using ShardingCore.Core;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Sharding.Abstractions;
@ -34,5 +35,8 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
bool IsUnion();
bool IsNotSupport();
int? GetMaxQueryConnectionsLimit();
ConnectionModeEnum? GetConnectionMode();
}
}

View File

@ -0,0 +1,78 @@
using System;
using System.Linq.Expressions;
using ShardingCore.Core;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
using ShardingCore.Sharding.Visitors.ShardingExtractParameters;
/*
* @Author: xjm
* @Description:
* @Date: DATE TIME
* @Email: 326308290@qq.com
*/
namespace ShardingCore.ShardingExecutors
{
public class CompileParameter:ICompileParameter
{
private readonly IShardingDbContext _shardingDbContext;
private readonly Expression _nativeQueryExpression;
private readonly bool _isNotSupport;
private readonly int? _maxQueryConnectionsLimit;
private readonly ConnectionModeEnum? _connectionMode;
private readonly bool? _readOnly;
private readonly Action<ShardingRouteContext> _shardingRouteConfigure;
public CompileParameter(IShardingDbContext shardingDbContext,Expression shardingQueryExpression)
{
_shardingDbContext = shardingDbContext;
var shardingQueryableExtractParameter = new ShardingQueryableExtractParameterVisitor();
_nativeQueryExpression = shardingQueryableExtractParameter.Visit(shardingQueryExpression);
var extractShardingParameter = shardingQueryableExtractParameter.ExtractShardingParameter();
_shardingRouteConfigure = extractShardingParameter.ShardingQueryableAsRouteOptions?.RouteConfigure;
_isNotSupport = extractShardingParameter.IsNotSupport;
_maxQueryConnectionsLimit = extractShardingParameter.ShardingQueryableUseConnectionModeOptions?.MaxQueryConnectionsLimit;
_connectionMode = extractShardingParameter.ShardingQueryableUseConnectionModeOptions?.ConnectionMode;
if (shardingDbContext.IsUseReadWriteSeparation())
{
_readOnly = extractShardingParameter?.ShardingQueryableReadWriteSeparationOptions?.RouteReadConnect??shardingDbContext.CurrentIsReadWriteSeparation();
}
}
public IShardingDbContext GetShardingDbContext()
{
return _shardingDbContext;
}
public Expression GetNativeQueryExpression()
{
return _nativeQueryExpression;
}
public bool IsNotSupport()
{
return _isNotSupport;
}
public int? GetMaxQueryConnectionsLimit()
{
return _maxQueryConnectionsLimit;
}
public ConnectionModeEnum? GetConnectionMode()
{
return _connectionMode;
}
public bool? ReadOnly()
{
return _readOnly;
}
public Action<ShardingRouteContext> GetAsRoute()
{
return _shardingRouteConfigure;
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
using ShardingCore.Sharding.ShardingExecutors;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
/*
* @Author: xjm
* @Description:
* @Date: DATE TIME
* @Email: 326308290@qq.com
*/
namespace ShardingCore.ShardingExecutors
{
internal class CustomerQueryScope:IDisposable
{
private readonly ShardingRouteScope _shardingRouteScope;
private readonly CustomerReadWriteScope _customerReadWriteScope;
private readonly bool _hasCustomerQuery;
public CustomerQueryScope(ICompileParameter compileParameter)
{
_hasCustomerQuery = compileParameter.HasCustomerQuery();
if (_hasCustomerQuery)
{
var asRoute = compileParameter.GetAsRoute();
if ( asRoute!= null)
{
var shardingRouteManager = ShardingContainer.GetService<IShardingRouteManager>();
_shardingRouteScope = shardingRouteManager.CreateScope();
asRoute.Invoke(shardingRouteManager.Current);
}
var readOnly = compileParameter.ReadOnly();
if (readOnly.HasValue)
{
_customerReadWriteScope = new CustomerReadWriteScope(compileParameter.GetShardingDbContext(), readOnly.Value);
}
}
}
public void Dispose()
{
if (_hasCustomerQuery)
{
_shardingRouteScope?.Dispose();
_customerReadWriteScope?.Dispose();
}
}
}
}

View File

@ -0,0 +1,44 @@
using System;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
/*
* @Author: xjm
* @Description:
* @Date: DATE TIME
* @Email: 326308290@qq.com
*/
namespace ShardingCore.Sharding.ShardingExecutors
{
internal class CustomerReadWriteScope:IDisposable
{
private readonly IShardingDbContext _shardingDbContext;
private readonly bool _readOnly;
public CustomerReadWriteScope(IShardingDbContext shardingDbContext,bool readOnly)
{
_shardingDbContext = shardingDbContext;
_readOnly = readOnly;
if (_readOnly)
{
_shardingDbContext.ReadWriteSeparationReadOnly();
}
else
{
_shardingDbContext.ReadWriteSeparationWriteOnly();
}
}
public void Dispose()
{
if (_readOnly)
{
_shardingDbContext.ReadWriteSeparationWriteOnly();
}
else
{
_shardingDbContext.ReadWriteSeparationReadOnly();
}
}
}
}

View File

@ -3,6 +3,10 @@ using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using ShardingCore.Extensions;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
using ShardingCore.Sharding.Visitors.ShardingExtractParameters;
using ShardingCore.ShardingExecutors;
namespace ShardingCore.Sharding.ShardingExecutors
{
@ -18,32 +22,51 @@ namespace ShardingCore.Sharding.ShardingExecutors
}
public TResult Execute<TResult>(IShardingDbContext shardingDbContext, Expression query)
{
var queryCompilerContext = _queryCompilerContextFactory.Create(shardingDbContext, query);
return _shardingTrackQueryExecutor.Execute<TResult>(queryCompilerContext);
var compileParameter = new CompileParameter(shardingDbContext,query);
var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
using (new CustomerQueryScope(compileParameter))
{
return _shardingTrackQueryExecutor.Execute<TResult>(queryCompilerContext);
}
}
#if !EFCORE2
public TResult ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query,
CancellationToken cancellationToken = new CancellationToken())
{
var queryCompilerContext = _queryCompilerContextFactory.Create(shardingDbContext, query);
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext);
var compileParameter = new CompileParameter(shardingDbContext,query);
var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
using (new CustomerQueryScope(compileParameter))
{
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext);
}
}
#endif
#if EFCORE2
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query)
{
var queryCompilerContext = _queryCompilerContextFactory.Create(shardingDbContext, query);
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext);
var compileParameter = new CompileParameter(shardingDbContext,query);
var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
using (new CustomerQueryScope(compileParameter))
{
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext);
}
}
public Task<TResult> ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query,
CancellationToken cancellationToken)
{
var queryCompilerContext = _queryCompilerContextFactory.Create(shardingDbContext, query);
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext, cancellationToken);
var compileParameter = new CompileParameter(shardingDbContext,query);
var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
using (new CustomerQueryScope(compileParameter))
{
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext, cancellationToken);
}
}
#endif
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Core;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
@ -114,6 +115,16 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _queryCompilerContext.IsNotSupport();
}
public int? GetMaxQueryConnectionsLimit()
{
return _queryCompilerContext.GetMaxQueryConnectionsLimit();
}
public ConnectionModeEnum? GetConnectionMode()
{
return _queryCompilerContext.GetConnectionMode();
}
public QueryCompilerExecutor GetQueryCompilerExecutor()
{
if (!hasQueryCompilerExecutor.HasValue)

View File

@ -1,6 +1,5 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
@ -10,7 +9,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using ShardingCore.Sharding.Visitors;
using ShardingCore.Core;
namespace ShardingCore.Sharding.ShardingExecutors
{
@ -27,28 +26,30 @@ namespace ShardingCore.Sharding.ShardingExecutors
private readonly bool _isUnion;
private readonly bool _isParallelQuery;
private readonly bool _isNotSupport;
private readonly int? _maxQueryConnectionsLimit;
private readonly ConnectionModeEnum? _connectionMode;
private QueryCompilerContext(IShardingDbContext shardingDbContext, Expression queryExpression)
private QueryCompilerContext(ICompileParameter compileParameter)
{
var shardingQueryableExtractParameter = new ShardingQueryableExtractParameter();
var expression = shardingQueryableExtractParameter.Visit(queryExpression);
_shardingDbContextType = shardingDbContext.GetType();
var compileParseResult = ShardingUtil.GetQueryCompileParseResultByExpression(expression, _shardingDbContextType);
_shardingDbContext = compileParameter.GetShardingDbContext();
_queryExpression = compileParameter.GetNativeQueryExpression();
_shardingDbContextType = _shardingDbContext.GetType();
var compileParseResult = ShardingUtil.GetQueryCompileParseResultByExpression(_queryExpression, _shardingDbContextType);
_queryEntities = compileParseResult.QueryEntities;
_isNoTracking = compileParseResult.IsNoTracking;
_isUnion = compileParseResult.IsUnion;
_shardingDbContext = shardingDbContext;
_queryExpression = expression;
_isNotSupport = shardingQueryableExtractParameter.IsNotSupportQuery();
_isNotSupport = compileParameter.IsNotSupport();
_maxQueryConnectionsLimit = compileParameter.GetMaxQueryConnectionsLimit();
_connectionMode = compileParameter.GetConnectionMode();
_entityMetadataManager = ShardingContainer.GetRequiredEntityMetadataManager(_shardingDbContextType);
//原生对象的原生查询如果是读写分离就需要启用并行查询
_isParallelQuery = shardingDbContext.IsUseReadWriteSeparation() && _shardingDbContext.CurrentIsReadWriteSeparation();
_isParallelQuery = compileParameter.ReadOnly().GetValueOrDefault();
}
public static QueryCompilerContext Create(IShardingDbContext shardingDbContext, Expression queryExpression)
public static QueryCompilerContext Create(ICompileParameter compileParameter)
{
return new QueryCompilerContext(shardingDbContext, queryExpression);
return new QueryCompilerContext(compileParameter);
}
public ISet<Type> GetQueryEntities()
@ -107,6 +108,16 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _isNotSupport;
}
public int? GetMaxQueryConnectionsLimit()
{
return _maxQueryConnectionsLimit;
}
public ConnectionModeEnum? GetConnectionMode()
{
return _connectionMode;
}
public QueryCompilerExecutor GetQueryCompilerExecutor()
{

View File

@ -16,13 +16,14 @@ using ShardingCore.Sharding.Visitors;
namespace ShardingCore.Sharding.ShardingExecutors
{
public class QueryCompilerContextFactory: IQueryCompilerContextFactory
public class QueryCompilerContextFactory : IQueryCompilerContextFactory
{
private static readonly IQueryableCombine _enumerableQueryableCombine;
private static readonly IQueryableCombine _allQueryableCombine;
private static readonly IQueryableCombine _constantQueryableCombine;
private static readonly IQueryableCombine _selectQueryableCombine;
private static readonly IQueryableCombine _whereQueryableCombine;
static QueryCompilerContextFactory()
{
_enumerableQueryableCombine = new EnumerableQueryableCombine();
@ -30,21 +31,23 @@ namespace ShardingCore.Sharding.ShardingExecutors
_constantQueryableCombine = new ConstantQueryableCombine();
_selectQueryableCombine = new SelectQueryableCombine();
_whereQueryableCombine = new WhereQueryableCombine();
}
public IQueryCompilerContext Create(IShardingDbContext shardingDbContext, Expression queryExpression)
}
public IQueryCompilerContext Create(ICompileParameter compileParameter)
{
var queryCompilerContext =
QueryCompilerContext.Create(shardingDbContext, queryExpression);
QueryCompilerContext.Create(compileParameter);
if (queryCompilerContext.GetQueryCompilerExecutor() is not null)
{
return queryCompilerContext;
}
var queryableCombine = GetQueryableCombine(queryCompilerContext);
var dataSourceRouteRuleEngineFactory = (IDataSourceRouteRuleEngineFactory)ShardingContainer.GetService(typeof(IDataSourceRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
var tableRouteRuleEngineFactory = (ITableRouteRuleEngineFactory)ShardingContainer.GetService(typeof(ITableRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
var queryCombineResult = queryableCombine.Combine(queryCompilerContext);
var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable(),shardingDbContext);
var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable(), compileParameter.GetShardingDbContext());
var tableRouteResults = tableRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable());
var routeResults = tableRouteResults as TableRouteResult[] ?? tableRouteResults.ToArray();
var mergeCombineCompilerContext = MergeQueryCompilerContext.Create(queryCompilerContext, queryCombineResult, dataSourceRouteResult,
@ -66,7 +69,6 @@ namespace ShardingCore.Sharding.ShardingExecutors
private IQueryableCombine GetMethodQueryableCombine(IQueryCompilerContext queryCompilerContext)
{
if (queryCompilerContext.GetQueryExpression() is MethodCallExpression methodCallExpression)
{
switch (methodCallExpression.Method.Name)
@ -92,6 +94,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _constantQueryableCombine;
}
}
throw new ShardingCoreException($"query expression:[{queryCompilerContext.GetQueryExpression().ShardingPrint()}] is not terminate operate");
}
}

View File

@ -89,6 +89,7 @@ namespace ShardingCore.Sharding
public bool TailComparerNeedReverse { get; } = true;
private int _maxParallelExecuteCount;
private ConnectionModeEnum _connectionMode;
public StreamMergeContext(IMergeQueryCompilerContext mergeQueryCompilerContext,
@ -119,8 +120,8 @@ namespace ShardingCore.Sharding
_notSupportShardingProvider = ShardingContainer.GetService<INotSupportShardingProvider>() ?? _defaultNotSupportShardingProvider;
_parallelDbContexts = new ConcurrentDictionary<DbContext, object>();
_maxParallelExecuteCount = _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit;
var maxParallelExecuteCount = _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit;
var connectionMode=_shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode;
if (IsSingleShardingEntityQuery() && !Skip.HasValue && IsCrossTable && !IsNotSupportSharding())
{
var singleShardingEntityType = GetSingleShardingEntityType();
@ -138,7 +139,7 @@ namespace ShardingCore.Sharding
methodName = ((MethodCallExpression)MergeQueryCompilerContext.GetQueryExpression()).Method.Name;
if (virtualTable.EntityQueryMetadata.TryGetConnectionsLimit(methodName, out var limit))
{
_maxParallelExecuteCount = Math.Min(limit, _maxParallelExecuteCount);
maxParallelExecuteCount = Math.Min(limit, maxParallelExecuteCount);
}
}
@ -154,6 +155,9 @@ namespace ShardingCore.Sharding
}
}
}
_maxParallelExecuteCount = mergeQueryCompilerContext.GetMaxQueryConnectionsLimit() ?? maxParallelExecuteCount;
_connectionMode = mergeQueryCompilerContext.GetConnectionMode() ?? connectionMode;
}
/// <summary>
/// 是否需要判断order
@ -343,13 +347,13 @@ namespace ShardingCore.Sharding
private ConnectionModeEnum CalcConnectionMode(int sqlCount)
{
switch (_shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode)
switch (_connectionMode)
{
case ConnectionModeEnum.MEMORY_STRICTLY:
case ConnectionModeEnum.CONNECTION_STRICTLY: return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode;
case ConnectionModeEnum.CONNECTION_STRICTLY: return _connectionMode;
default:
{
return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit < sqlCount
return GetMaxQueryConnectionsLimit() < sqlCount
? ConnectionModeEnum.CONNECTION_STRICTLY
: ConnectionModeEnum.MEMORY_STRICTLY; ;
}

View File

@ -0,0 +1,30 @@
using System;
using ShardingCore.Extensions.ShardingQueryableExtensions;
/*
* @Author: xjm
* @Description:
* @Date: DATE TIME
* @Email: 326308290@qq.com
*/
namespace ShardingCore.Sharding.Visitors.ShardingExtractParameters
{
internal class ShardingExtParameter
{
public bool IsNotSupport { get; }
public ShardingQueryableAsRouteOptions ShardingQueryableAsRouteOptions { get; }
public ShardingQueryableUseConnectionModeOptions ShardingQueryableUseConnectionModeOptions { get; }
public ShardingQueryableReadWriteSeparationOptions ShardingQueryableReadWriteSeparationOptions { get; }
public ShardingExtParameter(bool isNotSupport,
ShardingQueryableAsRouteOptions shardingQueryableAsRouteOptions,
ShardingQueryableUseConnectionModeOptions shardingQueryableUseConnectionModeOptions,
ShardingQueryableReadWriteSeparationOptions shardingQueryableReadWriteSeparationOptions)
{
IsNotSupport = isNotSupport;
ShardingQueryableAsRouteOptions = shardingQueryableAsRouteOptions;
ShardingQueryableUseConnectionModeOptions = shardingQueryableUseConnectionModeOptions;
ShardingQueryableReadWriteSeparationOptions = shardingQueryableReadWriteSeparationOptions;
}
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using ShardingCore.Extensions.ShardingQueryableExtensions;
namespace ShardingCore.Sharding.Visitors.ShardingExtractParameters
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 30 January 2022 00:48:30
* @Email: 326308290@qq.com
*/
internal class ShardingQueryableExtractParameterVisitor:ExpressionVisitor
{
private bool isNotSupport;
private ShardingQueryableUseConnectionModeOptions shardingQueryableUseConnectionModeOptions;
private ShardingQueryableAsRouteOptions shardingQueryableAsRouteOptions;
private ShardingQueryableReadWriteSeparationOptions shardingQueryableReadWriteSeparationOptions;
public ShardingExtParameter ExtractShardingParameter()
{
return new ShardingExtParameter(isNotSupport, shardingQueryableAsRouteOptions, shardingQueryableUseConnectionModeOptions, shardingQueryableReadWriteSeparationOptions);
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.IsGenericMethod)
{
var genericMethodDefinition = node.Method.GetGenericMethodDefinition();
// find cachable query extention calls
if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.NotSupportMethodInfo)
{
isNotSupport = true;
// cut out extension expression
return Visit(node.Arguments[0]);
} else if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.UseConnectionModeMethodInfo)
{
shardingQueryableUseConnectionModeOptions = node.Arguments
.OfType<ConstantExpression>()
.Where(o => o.Value is ShardingQueryableUseConnectionModeOptions)
.Select(o => (ShardingQueryableUseConnectionModeOptions)o.Value)
.Last();
return Visit(node.Arguments[0]);
}else if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.AsRouteMethodInfo)
{
shardingQueryableAsRouteOptions = node.Arguments
.OfType<ConstantExpression>()
.Where(o => o.Value is ShardingQueryableAsRouteOptions)
.Select(o => (ShardingQueryableAsRouteOptions)o.Value)
.Last();
return Visit(node.Arguments[0]);
}else if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.ReadWriteSeparationMethodInfo)
{
shardingQueryableReadWriteSeparationOptions = node.Arguments
.OfType<ConstantExpression>()
.Where(o => o.Value is ShardingQueryableReadWriteSeparationOptions)
.Select(o => (ShardingQueryableReadWriteSeparationOptions)o.Value)
.Last();
return Visit(node.Arguments[0]);
}
}
return base.VisitMethodCall(node);
}
}
}

View File

@ -1,37 +0,0 @@
using System;
using System.Linq.Expressions;
using ShardingCore.Extensions.ShardingQueryableExtensions;
namespace ShardingCore.Sharding.Visitors
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 30 January 2022 00:48:30
* @Email: 326308290@qq.com
*/
public class ShardingQueryableExtractParameter:ExpressionVisitor
{
private bool isNotSupport;
public bool IsNotSupportQuery()
{
return isNotSupport;
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.IsGenericMethod)
{
var genericMethodDefinition = node.Method.GetGenericMethodDefinition();
// find cachable query extention calls
if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.NotSupportMethodInfo)
{
isNotSupport = true;
// cut out extension expression
return Visit(node.Arguments[0]);
}
}
return base.VisitMethodCall(node);
}
}
}

View File

@ -28,6 +28,9 @@
<Compile Include="..\..\src\ShardingCore\**\*.cs" />
<Compile Remove="..\..\src\ShardingCore\obj\**" />
<Compile Remove="..\..\src\ShardingCore\bin\**" />
<Compile Update="..\..\src\ShardingCore\Sharding\ShardingExecutors\Abstractions\ICompileParameter.cs">
<Link>Sharding\ShardingExecutors\Abstractions\ICompileParameter.cs</Link>
</Compile>
</ItemGroup>

View File

@ -28,6 +28,12 @@
<Compile Include="..\..\src\ShardingCore\**\*.cs" />
<Compile Remove="..\..\src\ShardingCore\obj\**" />
<Compile Remove="..\..\src\ShardingCore\bin\**" />
<Compile Update="..\..\src\ShardingCore\Sharding\ShardingExecutors\CompileParameter.cs">
<Link>Sharding\ShardingExecutors\CompileParameter.cs</Link>
</Compile>
<Compile Update="..\..\src\ShardingCore\Sharding\ShardingExecutors\CustomerQueryScope.cs">
<Link>Sharding\ShardingExecutors\CustomerQueryScope.cs</Link>
</Compile>
</ItemGroup>