[#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;
using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions.ShardingQueryableExtensions;
namespace Sample.SqlServer.Controllers namespace Sample.SqlServer.Controllers
{ {
@ -174,6 +175,19 @@ namespace Sample.SqlServer.Controllers
}); });
} }
[HttpGet] [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) public IActionResult Get2([FromQuery] int p, [FromQuery] int s)
{ {
Stopwatch sp = new Stopwatch(); Stopwatch sp = new Stopwatch();

View File

@ -7,10 +7,8 @@ using ShardingCore.Sharding.ShardingExecutors.Abstractions;
namespace ShardingCore.Core.NotSupportShardingProviders namespace ShardingCore.Core.NotSupportShardingProviders
{ {
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
public interface INotSupportShardingProvider public interface INotSupportShardingProvider
{ {
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
void CheckNotSupportSharding(IQueryCompilerContext queryCompilerContext); void CheckNotSupportSharding(IQueryCompilerContext queryCompilerContext);
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")] [Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext); 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 System.Reflection;
using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.Internal;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.QueryRouteManagers;
namespace ShardingCore.Extensions.ShardingQueryableExtensions
{
/* /*
* @Author: xjm * @Author: xjm
* @Description: * @Description:
* @Date: Sunday, 30 January 2022 00:12:37 * @Date: Sunday, 30 January 2022 00:12:37
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
namespace ShardingCore.Extensions.ShardingQueryableExtensions
{
/// <summary>
/// 分片查询额外扩展
/// </summary>
public static class EntityFrameworkShardingQueryableExtension public static class EntityFrameworkShardingQueryableExtension
{ {
internal static readonly MethodInfo NotSupportMethodInfo internal static readonly MethodInfo NotSupportMethodInfo
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(NotSupport)).Single(); = typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(NotSupport)).Single();
internal static readonly MethodInfo AsRouteMethodInfo internal static readonly MethodInfo AsRouteMethodInfo
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(AsRoute)).Single(); = typeof(EntityFrameworkShardingQueryableExtension)
internal static readonly MethodInfo UseConfigMethodInfo .GetTypeInfo()
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(UseConfig)).Single(); .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 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 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> /// <summary>
/// 标记当前操作是不支持分片的可以自行才用union all /// 标记当前操作是不支持分片的可以自行才用union all
@ -45,32 +62,37 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
source.Expression)) source.Expression))
: source; : source;
} }
/// <summary>
/// 开启提示路由的前提下手动指定表、手动指定数据源 /// <summary>
/// </summary> /// 开启提示路由的前提下手动指定表、手动指定数据源
/// <param name="source"></param> /// </summary>
/// <param name="routeConfigure"></param> /// <param name="source"></param>
/// <typeparam name="TEntity"></typeparam> /// <param name="routeConfigure"></param>
/// <returns></returns> /// <typeparam name="TEntity"></typeparam>
public static IQueryable<TEntity> AsRoute<TEntity>(this IQueryable<TEntity> source,Action<ShardingQueryableAsRouteOptions> routeConfigure) /// <returns></returns>
public static IQueryable<TEntity> AsRoute<TEntity>(this IQueryable<TEntity> source, Action<ShardingRouteContext> routeConfigure)
{ {
Check.NotNull(source, nameof(source)); Check.NotNull(source, nameof(source));
Check.NotNull(routeConfigure, nameof(routeConfigure)); Check.NotNull(routeConfigure, nameof(routeConfigure));
return source; var shardingQueryableAsRouteOptions = new ShardingQueryableAsRouteOptions(routeConfigure);
return source.AsRoute(shardingQueryableAsRouteOptions);
} }
/// <summary> internal static IQueryable<TEntity> AsRoute<TEntity>(this IQueryable<TEntity> source, ShardingQueryableAsRouteOptions shardingQueryableAsRouteOptions)
/// 使用哪个配置多配置下有效
/// </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)
{ {
Check.NotNull(source, nameof(source)); 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>
/// 设置连接而模式 /// 设置连接而模式
/// </summary> /// </summary>
@ -80,13 +102,30 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
/// <returns></returns> /// <returns></returns>
/// <exception cref="ArgumentException"></exception> /// <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)); Check.NotNull(source, nameof(source));
if (maxQueryConnectionsLimit <= 0) if (maxQueryConnectionsLimit <= 0)
throw new ArgumentException($"{nameof(UseConnectionMode)} {nameof(maxQueryConnectionsLimit)} should >=1"); 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>
/// 走读库 /// 走读库
/// </summary> /// </summary>
@ -97,6 +136,7 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
{ {
return source.ReadWriteSeparation(true); return source.ReadWriteSeparation(true);
} }
/// <summary> /// <summary>
/// 走写库 /// 走写库
/// </summary> /// </summary>
@ -107,6 +147,7 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
{ {
return source.ReadWriteSeparation(false); return source.ReadWriteSeparation(false);
} }
/// <summary> /// <summary>
/// 自定义读写分离走什么库 /// 自定义读写分离走什么库
/// </summary> /// </summary>
@ -114,10 +155,20 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
/// <param name="routeReadConnect"></param> /// <param name="routeReadConnect"></param>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
/// <returns></returns> /// <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)); 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 * @Date: Monday, 31 January 2022 00:15:37
* @Email: 326308290@qq.com * @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) 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 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 System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.Internal;
using ShardingCore.Core;
using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -34,5 +35,8 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")] [Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
bool IsUnion(); bool IsUnion();
bool IsNotSupport(); 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.Linq.Expressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ShardingCore.Extensions;
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
using ShardingCore.Sharding.Visitors.ShardingExtractParameters;
using ShardingCore.ShardingExecutors;
namespace ShardingCore.Sharding.ShardingExecutors namespace ShardingCore.Sharding.ShardingExecutors
{ {
@ -18,32 +22,51 @@ namespace ShardingCore.Sharding.ShardingExecutors
} }
public TResult Execute<TResult>(IShardingDbContext shardingDbContext, Expression query) public TResult Execute<TResult>(IShardingDbContext shardingDbContext, Expression query)
{ {
var queryCompilerContext = _queryCompilerContextFactory.Create(shardingDbContext, query); var compileParameter = new CompileParameter(shardingDbContext,query);
return _shardingTrackQueryExecutor.Execute<TResult>(queryCompilerContext); var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
using (new CustomerQueryScope(compileParameter))
{
return _shardingTrackQueryExecutor.Execute<TResult>(queryCompilerContext);
}
} }
#if !EFCORE2 #if !EFCORE2
public TResult ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query, public TResult ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query,
CancellationToken cancellationToken = new CancellationToken()) CancellationToken cancellationToken = new CancellationToken())
{ {
var queryCompilerContext = _queryCompilerContextFactory.Create(shardingDbContext, query); var compileParameter = new CompileParameter(shardingDbContext,query);
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext); var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
using (new CustomerQueryScope(compileParameter))
{
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext);
}
} }
#endif #endif
#if EFCORE2 #if EFCORE2
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query) public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query)
{ {
var queryCompilerContext = _queryCompilerContextFactory.Create(shardingDbContext, query); var compileParameter = new CompileParameter(shardingDbContext,query);
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext); var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
using (new CustomerQueryScope(compileParameter))
{
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext);
}
} }
public Task<TResult> ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query, public Task<TResult> ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var queryCompilerContext = _queryCompilerContextFactory.Create(shardingDbContext, query); var compileParameter = new CompileParameter(shardingDbContext,query);
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext, cancellationToken); var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
using (new CustomerQueryScope(compileParameter))
{
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext, cancellationToken);
}
} }
#endif #endif
} }

View File

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

View File

@ -1,6 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -10,7 +9,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Sharding.Visitors; using ShardingCore.Core;
namespace ShardingCore.Sharding.ShardingExecutors namespace ShardingCore.Sharding.ShardingExecutors
{ {
@ -27,28 +26,30 @@ namespace ShardingCore.Sharding.ShardingExecutors
private readonly bool _isUnion; private readonly bool _isUnion;
private readonly bool _isParallelQuery; private readonly bool _isParallelQuery;
private readonly bool _isNotSupport; 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(); _shardingDbContext = compileParameter.GetShardingDbContext();
var expression = shardingQueryableExtractParameter.Visit(queryExpression); _queryExpression = compileParameter.GetNativeQueryExpression();
_shardingDbContextType = shardingDbContext.GetType(); _shardingDbContextType = _shardingDbContext.GetType();
var compileParseResult = ShardingUtil.GetQueryCompileParseResultByExpression(expression, _shardingDbContextType); var compileParseResult = ShardingUtil.GetQueryCompileParseResultByExpression(_queryExpression, _shardingDbContextType);
_queryEntities = compileParseResult.QueryEntities; _queryEntities = compileParseResult.QueryEntities;
_isNoTracking = compileParseResult.IsNoTracking; _isNoTracking = compileParseResult.IsNoTracking;
_isUnion = compileParseResult.IsUnion; _isUnion = compileParseResult.IsUnion;
_shardingDbContext = shardingDbContext; _isNotSupport = compileParameter.IsNotSupport();
_queryExpression = expression; _maxQueryConnectionsLimit = compileParameter.GetMaxQueryConnectionsLimit();
_isNotSupport = shardingQueryableExtractParameter.IsNotSupportQuery(); _connectionMode = compileParameter.GetConnectionMode();
_entityMetadataManager = ShardingContainer.GetRequiredEntityMetadataManager(_shardingDbContextType); _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() public ISet<Type> GetQueryEntities()
@ -107,6 +108,16 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _isNotSupport; return _isNotSupport;
} }
public int? GetMaxQueryConnectionsLimit()
{
return _maxQueryConnectionsLimit;
}
public ConnectionModeEnum? GetConnectionMode()
{
return _connectionMode;
}
public QueryCompilerExecutor GetQueryCompilerExecutor() public QueryCompilerExecutor GetQueryCompilerExecutor()
{ {

View File

@ -16,13 +16,14 @@ using ShardingCore.Sharding.Visitors;
namespace ShardingCore.Sharding.ShardingExecutors namespace ShardingCore.Sharding.ShardingExecutors
{ {
public class QueryCompilerContextFactory: IQueryCompilerContextFactory public class QueryCompilerContextFactory : IQueryCompilerContextFactory
{ {
private static readonly IQueryableCombine _enumerableQueryableCombine; private static readonly IQueryableCombine _enumerableQueryableCombine;
private static readonly IQueryableCombine _allQueryableCombine; private static readonly IQueryableCombine _allQueryableCombine;
private static readonly IQueryableCombine _constantQueryableCombine; private static readonly IQueryableCombine _constantQueryableCombine;
private static readonly IQueryableCombine _selectQueryableCombine; private static readonly IQueryableCombine _selectQueryableCombine;
private static readonly IQueryableCombine _whereQueryableCombine; private static readonly IQueryableCombine _whereQueryableCombine;
static QueryCompilerContextFactory() static QueryCompilerContextFactory()
{ {
_enumerableQueryableCombine = new EnumerableQueryableCombine(); _enumerableQueryableCombine = new EnumerableQueryableCombine();
@ -30,21 +31,23 @@ namespace ShardingCore.Sharding.ShardingExecutors
_constantQueryableCombine = new ConstantQueryableCombine(); _constantQueryableCombine = new ConstantQueryableCombine();
_selectQueryableCombine = new SelectQueryableCombine(); _selectQueryableCombine = new SelectQueryableCombine();
_whereQueryableCombine = new WhereQueryableCombine(); _whereQueryableCombine = new WhereQueryableCombine();
} }
public IQueryCompilerContext Create(IShardingDbContext shardingDbContext, Expression queryExpression)
public IQueryCompilerContext Create(ICompileParameter compileParameter)
{ {
var queryCompilerContext = var queryCompilerContext =
QueryCompilerContext.Create(shardingDbContext, queryExpression); QueryCompilerContext.Create(compileParameter);
if (queryCompilerContext.GetQueryCompilerExecutor() is not null) if (queryCompilerContext.GetQueryCompilerExecutor() is not null)
{ {
return queryCompilerContext; return queryCompilerContext;
} }
var queryableCombine = GetQueryableCombine(queryCompilerContext); var queryableCombine = GetQueryableCombine(queryCompilerContext);
var dataSourceRouteRuleEngineFactory = (IDataSourceRouteRuleEngineFactory)ShardingContainer.GetService(typeof(IDataSourceRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType())); var dataSourceRouteRuleEngineFactory = (IDataSourceRouteRuleEngineFactory)ShardingContainer.GetService(typeof(IDataSourceRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
var tableRouteRuleEngineFactory = (ITableRouteRuleEngineFactory)ShardingContainer.GetService(typeof(ITableRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType())); var tableRouteRuleEngineFactory = (ITableRouteRuleEngineFactory)ShardingContainer.GetService(typeof(ITableRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
var queryCombineResult = queryableCombine.Combine(queryCompilerContext); 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 tableRouteResults = tableRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable());
var routeResults = tableRouteResults as TableRouteResult[] ?? tableRouteResults.ToArray(); var routeResults = tableRouteResults as TableRouteResult[] ?? tableRouteResults.ToArray();
var mergeCombineCompilerContext = MergeQueryCompilerContext.Create(queryCompilerContext, queryCombineResult, dataSourceRouteResult, var mergeCombineCompilerContext = MergeQueryCompilerContext.Create(queryCompilerContext, queryCombineResult, dataSourceRouteResult,
@ -66,7 +69,6 @@ namespace ShardingCore.Sharding.ShardingExecutors
private IQueryableCombine GetMethodQueryableCombine(IQueryCompilerContext queryCompilerContext) private IQueryableCombine GetMethodQueryableCombine(IQueryCompilerContext queryCompilerContext)
{ {
if (queryCompilerContext.GetQueryExpression() is MethodCallExpression methodCallExpression) if (queryCompilerContext.GetQueryExpression() is MethodCallExpression methodCallExpression)
{ {
switch (methodCallExpression.Method.Name) switch (methodCallExpression.Method.Name)
@ -92,7 +94,8 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _constantQueryableCombine; return _constantQueryableCombine;
} }
} }
throw new ShardingCoreException($"query expression:[{queryCompilerContext.GetQueryExpression().ShardingPrint()}] is not terminate operate"); 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; public bool TailComparerNeedReverse { get; } = true;
private int _maxParallelExecuteCount; private int _maxParallelExecuteCount;
private ConnectionModeEnum _connectionMode;
public StreamMergeContext(IMergeQueryCompilerContext mergeQueryCompilerContext, public StreamMergeContext(IMergeQueryCompilerContext mergeQueryCompilerContext,
@ -119,8 +120,8 @@ namespace ShardingCore.Sharding
_notSupportShardingProvider = ShardingContainer.GetService<INotSupportShardingProvider>() ?? _defaultNotSupportShardingProvider; _notSupportShardingProvider = ShardingContainer.GetService<INotSupportShardingProvider>() ?? _defaultNotSupportShardingProvider;
_parallelDbContexts = new ConcurrentDictionary<DbContext, object>(); _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()) if (IsSingleShardingEntityQuery() && !Skip.HasValue && IsCrossTable && !IsNotSupportSharding())
{ {
var singleShardingEntityType = GetSingleShardingEntityType(); var singleShardingEntityType = GetSingleShardingEntityType();
@ -138,7 +139,7 @@ namespace ShardingCore.Sharding
methodName = ((MethodCallExpression)MergeQueryCompilerContext.GetQueryExpression()).Method.Name; methodName = ((MethodCallExpression)MergeQueryCompilerContext.GetQueryExpression()).Method.Name;
if (virtualTable.EntityQueryMetadata.TryGetConnectionsLimit(methodName, out var limit)) 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> /// <summary>
/// 是否需要判断order /// 是否需要判断order
@ -343,13 +347,13 @@ namespace ShardingCore.Sharding
private ConnectionModeEnum CalcConnectionMode(int sqlCount) private ConnectionModeEnum CalcConnectionMode(int sqlCount)
{ {
switch (_shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode) switch (_connectionMode)
{ {
case ConnectionModeEnum.MEMORY_STRICTLY: case ConnectionModeEnum.MEMORY_STRICTLY:
case ConnectionModeEnum.CONNECTION_STRICTLY: return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode; case ConnectionModeEnum.CONNECTION_STRICTLY: return _connectionMode;
default: default:
{ {
return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit < sqlCount return GetMaxQueryConnectionsLimit() < sqlCount
? ConnectionModeEnum.CONNECTION_STRICTLY ? ConnectionModeEnum.CONNECTION_STRICTLY
: ConnectionModeEnum.MEMORY_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 Include="..\..\src\ShardingCore\**\*.cs" />
<Compile Remove="..\..\src\ShardingCore\obj\**" /> <Compile Remove="..\..\src\ShardingCore\obj\**" />
<Compile Remove="..\..\src\ShardingCore\bin\**" /> <Compile Remove="..\..\src\ShardingCore\bin\**" />
<Compile Update="..\..\src\ShardingCore\Sharding\ShardingExecutors\Abstractions\ICompileParameter.cs">
<Link>Sharding\ShardingExecutors\Abstractions\ICompileParameter.cs</Link>
</Compile>
</ItemGroup> </ItemGroup>

View File

@ -28,6 +28,12 @@
<Compile Include="..\..\src\ShardingCore\**\*.cs" /> <Compile Include="..\..\src\ShardingCore\**\*.cs" />
<Compile Remove="..\..\src\ShardingCore\obj\**" /> <Compile Remove="..\..\src\ShardingCore\obj\**" />
<Compile Remove="..\..\src\ShardingCore\bin\**" /> <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> </ItemGroup>