添加测试代码

This commit is contained in:
xuejiaming 2022-06-02 12:25:26 +08:00
parent 24a51a8ecf
commit b17a841668
21 changed files with 151 additions and 37 deletions

View File

@ -382,5 +382,12 @@ namespace Sample.SqlServer.Controllers
return Ok();
}
[HttpGet]
public async Task<IActionResult> Get6()
{
var sysUserSalaries = await _defaultTableDbContext.Set<SysUserSalary>().Where(o=>o.DateOfMonth==202101).ToListAsync();
return Ok();
}
}
}

View File

@ -16,7 +16,7 @@ namespace Sample.SqlServer.Domain.Entities
/// 每月的金额
/// </summary>
[ShardingTableKey]
public int DateOfMonth { get; set; }
public int? DateOfMonth { get; set; }
/// <summary>
/// 工资
/// </summary>

View File

@ -14,11 +14,11 @@ namespace Sample.SqlServer.Shardings
public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute<SysUserMod>
{
/// <summary>
/// ソェニ<EFBFBD>睫セツキモノ
/// 开启提示路由
/// </summary>
protected override bool EnableHintRoute => true;
/// <summary>
/// ソェニ<EFBFBD>マムヤツキモノ
/// 开启断言路由
/// </summary>
protected override bool EnableAssertRoute => true;

View File

@ -14,9 +14,12 @@ namespace Sample.SqlServer.Shardings
builder.PaginationSequence(o => o.Id)
.UseRouteComparer(Comparer<string>.Default)
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch);
//设置当
builder.PaginationSequence(o => o.DateOfMonth)
.UseRouteComparer(Comparer<string>.Default)
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone(10);
builder.PaginationSequence(o => o.Salary)
.UseRouteComparer(Comparer<string>.Default)
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone();
builder.ConfigReverseShardingPage(0.5d,10000L);
}

View File

@ -16,7 +16,7 @@ namespace Sample.SqlServer.Shardings
* @Date: Monday, 01 February 2021 15:54:55
* @Email: 326308290@qq.com
*/
public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute<SysUserSalary,int>
public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute<SysUserSalary,int?>
{
public override string ShardingKeyToTail(object shardingKey)
@ -46,13 +46,13 @@ namespace Sample.SqlServer.Shardings
}
protected string TimeFormatToTail(int time)
protected string TimeFormatToTail(int? time)
{
var dateOfMonth=DateTime.ParseExact($"{time}","yyyyMM",System.Globalization.CultureInfo.InvariantCulture,System.Globalization.DateTimeStyles.AdjustToUniversal);
return $"{dateOfMonth:yyyyMM}";
}
public override Func<string, bool> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator)
public override Func<string, bool> GetRouteToFilter(int? shardingKey, ShardingOperatorEnum shardingOperator)
{
var t = TimeFormatToTail(shardingKey);
switch (shardingOperator)

View File

@ -12,7 +12,10 @@ using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.DbContextCreator
{
/// <summary>
///
/// dbcontext的创建者
/// 反射创建默认框架采用这个可以,
/// 如果需要dbcontext构造函数支持依赖注入参数
/// 可以自行重写这个接口
/// </summary>
/// Author: xjm
/// Created: 2022/4/2 21:15:09
@ -25,7 +28,13 @@ namespace ShardingCore.Core.DbContextCreator
ShardingCoreHelper.CheckContextConstructors<TShardingDbContext>();
_creator = ShardingCoreHelper.CreateActivator<TShardingDbContext>();
}
public DbContext CreateDbContext(DbContext mainDbContext, ShardingDbContextOptions shardingDbContextOptions)
/// <summary>
/// 如何创建dbcontext
/// </summary>
/// <param name="shellDbContext"></param>
/// <param name="shardingDbContextOptions"></param>
/// <returns></returns>
public DbContext CreateDbContext(DbContext shellDbContext, ShardingDbContextOptions shardingDbContextOptions)
{
var dbContext = _creator(shardingDbContextOptions);
if (dbContext is IShardingTableDbContext shardingTableDbContext)

View File

@ -11,14 +11,20 @@ using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.DbContextCreator
{
/// <summary>
///
/// dbcontext创建者
/// </summary>
/// Author: xjm
/// Created: 2022/4/2 21:12:17
/// Email: 326308290@qq.com
public interface IDbContextCreator
{
public DbContext CreateDbContext(DbContext mainDbContext, ShardingDbContextOptions shardingDbContextOptions);
/// <summary>
/// 创建dbcontext
/// </summary>
/// <param name="shellDbContext">最外部的dbcontext也就是壳不具备真正的执行</param>
/// <param name="shardingDbContextOptions">返回dbcontext的配置路由等信息</param>
/// <returns></returns>
public DbContext CreateDbContext(DbContext shellDbContext, ShardingDbContextOptions shardingDbContextOptions);
}
public interface IDbContextCreator<TShardingDbContext> : IDbContextCreator

View File

@ -13,7 +13,6 @@ namespace ShardingCore.Core.DbContextCreator
*/
public class ShardingDbContextOptions
{
public ShardingDbContextOptions(DbContextOptions dbContextOptions, IRouteTail routeTail)
{
RouteTail = routeTail;

View File

@ -15,6 +15,9 @@ namespace ShardingCore.Core.PhysicTables
/// </summary>
public interface IPhysicTable
{
/// <summary>
/// 对象信息
/// </summary>
EntityMetadata EntityMetadata { get; }
/// <summary>
/// 表全称

View File

@ -2,29 +2,50 @@ using System;
namespace ShardingCore.Core.VirtualRoutes
{
/// <summary>
/// 高性能路由条件组合委托
/// 无需compile支持路由条件直接组合and 和 or
/// </summary>
public class RoutePredicateExpression
{
private static readonly Func<string, bool> _defaultRoutePredicate = tail => true;
private static readonly Func<string, bool> _defaultFalseRoutePredicate = tail => false;
/// <summary>
/// 默认创建一个true委托
/// </summary>
public static RoutePredicateExpression Default => new RoutePredicateExpression();
/// <summary>
/// 默认创建一个false委托
/// </summary>
public static RoutePredicateExpression DefaultFalse => new RoutePredicateExpression(_defaultFalseRoutePredicate);
private readonly Func<string, bool> _routePredicate;
public RoutePredicateExpression():this(_defaultRoutePredicate)
{
}
public static RoutePredicateExpression Default => new RoutePredicateExpression();
public static RoutePredicateExpression DefaultFalse => new RoutePredicateExpression(_defaultFalseRoutePredicate);
public RoutePredicateExpression(Func<string, bool> routePredicate)
{
_routePredicate = routePredicate??throw new ArgumentNullException(nameof(routePredicate));
}
/// <summary>
/// and链接当前委托和外部传入的委托
/// </summary>
/// <param name="routePredicateExpression"></param>
/// <returns></returns>
public RoutePredicateExpression And(RoutePredicateExpression routePredicateExpression)
{
var routePredicate = routePredicateExpression.GetRoutePredicate();
Func<string, bool> func = tail => _routePredicate(tail)&&routePredicate(tail);
return new RoutePredicateExpression(func);
}
/// <summary>
/// or链接当前委托和外部传入的委托
/// </summary>
/// <param name="routePredicateExpression"></param>
/// <returns></returns>
public RoutePredicateExpression Or(RoutePredicateExpression routePredicateExpression)
{
var routePredicate = routePredicateExpression.GetRoutePredicate();
@ -32,6 +53,10 @@ namespace ShardingCore.Core.VirtualRoutes
return new RoutePredicateExpression(func);
}
/// <summary>
/// 返回当前表达式的路由委托条件
/// </summary>
/// <returns></returns>
public Func<string, bool> GetRoutePredicate()
{
return _routePredicate;

View File

@ -51,11 +51,28 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes
{
/// <summary>
/// 返回null就是表示不开启分页配置
/// 譬如如下配置
/// <code><![CDATA[builder.PaginationSequence(o => o.DateOfMonth)
/// .UseRouteComparer(Comparer<string>.Default)
/// .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch)
/// .UseAppendIfOrderNone(10);]]></code>
/// 表示当前分页配置如果使用<code>DateOfMonth</code>属性排序并且只要符合属性属于这个对象或者名称一样并且只要是第一个排序即可
/// 当前排序将可以使用高性能排序,这边需要设置一个当前属性<code>DateOfMonth</code> order by asc的时候当前分表多表是如何排序的
/// </summary>
/// <returns></returns>
IPaginationConfiguration<TEntity> CreatePaginationConfiguration();
/// <summary>
/// 配置查询
/// <code><![CDATA[
/// //DateOfMonth的排序和月份分片的后缀一致所以用true如果false,无果无关就不需要配置
/// builder.ShardingTailComparer(Comparer<string>.Default, false);
/// //表示他是倒叙
/// builder.AddOrder(o => o.DateOfMonth, false);
/// //
/// builder.AddDefaultSequenceQueryTrip(false, CircuitBreakerMethodNameEnum.FirstOrDefault, CircuitBreakerMethodNameEnum.Enumerator);
///
/// builder.AddConnectionsLimit(2, LimitMethodNameEnum.First, LimitMethodNameEnum.FirstOrDefault, LimitMethodNameEnum.Any, LimitMethodNameEnum.LastOrDefault, LimitMethodNameEnum.Last, LimitMethodNameEnum.Max, LimitMethodNameEnum.Min);
/// builder.AddConnectionsLimit(1, LimitMethodNameEnum.Enumerator);]]></code>
/// </summary>
/// <returns></returns>
IEntityQueryConfiguration<TEntity> CreateEntityQueryConfiguration();

View File

@ -122,7 +122,7 @@ namespace ShardingCore
//分表引擎工程
services.TryAddSingleton<IParallelTableManager<TShardingDbContext>, ParallelTableManager<TShardingDbContext>>();
services.TryAddSingleton<IRouteTailFactory, RouteTailFactory>();
services.TryAddSingleton<IShardingComplierExecutor, DefaultShardingComplierExecutor>();
services.TryAddSingleton<IShardingCompilerExecutor, DefaultShardingCompilerExecutor>();
services.TryAddSingleton<IQueryCompilerContextFactory, QueryCompilerContextFactory>();
services.TryAddSingleton<IShardingQueryExecutor, DefaultShardingQueryExecutor>();
services.TryAddSingleton<IReadWriteConnectorFactory, ReadWriteConnectorFactory>();

View File

@ -14,26 +14,24 @@ using System.Threading.Tasks;
namespace ShardingCore.EFCores
{
/**
*
*
* Authorxuejiaming
* Created: 2020/12/28 13:58:46
**/
/// <summary>
/// 当前查询编译拦截
/// </summary>
public class ShardingQueryCompiler : IQueryCompiler
{
private readonly IShardingDbContext _shardingDbContext;
private readonly IShardingComplierExecutor _shardingComplierExecutor;
private readonly IShardingCompilerExecutor _shardingCompilerExecutor;
public ShardingQueryCompiler(ICurrentDbContext currentContext)
{
_shardingDbContext = currentContext.Context as IShardingDbContext?? throw new ShardingCoreException("db context operator is not IShardingDbContext");
_shardingComplierExecutor = ShardingContainer.GetService<IShardingComplierExecutor>();
_shardingDbContext = currentContext.Context as IShardingDbContext ??
throw new ShardingCoreException("db context operator is not IShardingDbContext");
_shardingCompilerExecutor = ShardingContainer.GetService<IShardingCompilerExecutor>();
}
public TResult Execute<TResult>(Expression query)
{
return _shardingComplierExecutor.Execute<TResult>(_shardingDbContext, query);
return _shardingCompilerExecutor.Execute<TResult>(_shardingDbContext, query);
}
@ -41,7 +39,7 @@ namespace ShardingCore.EFCores
public TResult ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
{
return _shardingComplierExecutor.ExecuteAsync<TResult>(_shardingDbContext, query, cancellationToken);
return _shardingCompilerExecutor.ExecuteAsync<TResult>(_shardingDbContext, query, cancellationToken);
}
[ExcludeFromCodeCoverage]
@ -59,16 +57,14 @@ namespace ShardingCore.EFCores
#endif
#if EFCORE2
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression query)
{
return _shardingComplierExecutor.ExecuteAsync<TResult>(_shardingDbContext, query);
return _shardingCompilerExecutor.ExecuteAsync<TResult>(_shardingDbContext, query);
}
public Task<TResult> ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
{
return _shardingComplierExecutor.ExecuteAsync<TResult>(_shardingDbContext, query, cancellationToken);
return _shardingCompilerExecutor.ExecuteAsync<TResult>(_shardingDbContext, query, cancellationToken);
}
[ExcludeFromCodeCoverage]
@ -89,6 +85,5 @@ namespace ShardingCore.EFCores
throw new NotImplementedException();
}
#endif
}
}

View File

@ -8,6 +8,9 @@ using ShardingCore.Sharding.Abstractions;
namespace ShardingCore
{
/// <summary>
/// 启动dbContext类型收集器用于初始化确定dbcontext 类型
/// </summary>
public interface IDbContextTypeCollector
{
Type ShardingDbContextType { get; }

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
namespace ShardingCore.Sharding.Abstractions
{
public interface IShardingComplierExecutor
public interface IShardingCompilerExecutor
{
/// <summary>

View File

@ -13,6 +13,10 @@ using Microsoft.EntityFrameworkCore.Internal;
namespace ShardingCore.Sharding.EntityQueryConfigurations
{
/// <summary>
/// 对象查询配置
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class EntityQueryBuilder<TEntity> where TEntity : class
{
private readonly EntityQueryMetadata _entityQueryMetadata;
@ -78,7 +82,6 @@ namespace ShardingCore.Sharding.EntityQueryConfigurations
/// <exception cref="ArgumentNullException"></exception>
public EntityQueryBuilder<TEntity> AddDefaultSequenceQueryTrip(bool isSameAsShardingTailComparer,params CircuitBreakerMethodNameEnum[] methodNames)
{
foreach (var methodName in methodNames)
{
_entityQueryMetadata.AddDefaultSequenceQueryTrip(isSameAsShardingTailComparer, methodName);

View File

@ -6,6 +6,9 @@ using System.Threading.Tasks;
namespace ShardingCore.Sharding.EntityQueryConfigurations
{
/// <summary>
/// 可以熔断的方法名
/// </summary>
public enum CircuitBreakerMethodNameEnum
{
First,
@ -19,6 +22,9 @@ namespace ShardingCore.Sharding.EntityQueryConfigurations
Contains,
Enumerator
}
/// <summary>
/// 配置限制最大连接数的方法名
/// </summary>
public enum LimitMethodNameEnum
{
First,

View File

@ -22,9 +22,17 @@ namespace ShardingCore.Sharding.PaginationConfigurations
/// <summary>
/// 使用哪个后缀比较
/// 设置的比较器是asc的情况下
/// </summary>
/// <param name="routeComparer"></param>
/// <returns></returns>
public PaginationOrderPropertyBuilder UseRouteComparerAsc(IComparer<string> routeComparer)
{
_paginationSequenceConfig.RouteComparer= routeComparer ?? throw new ArgumentException(nameof(routeComparer));
return this;
}
[Obsolete("plz use UseRouteComparerAsc")]
public PaginationOrderPropertyBuilder UseRouteComparer(IComparer<string> routeComparer)
{

View File

@ -19,6 +19,15 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
Expression GetQueryExpression();
IEntityMetadataManager GetEntityMetadataManager();
Type GetShardingDbContextType();
/// <summary>
/// 如果当前是QueryCompilerContext
/// 获取编译后的执行结果,如果当前是没有分表分库
/// 直接返回默认的dbcontext并且替换内部所有的dbcontext为执行dbcontext简单理解为原生查询
/// 如果当前是MergeQueryCompilerContext
/// 获取编译的执行结果,如果当前是有分表分库
/// 但是如果是只涉及到一张表那么也可以简单理解为原生查询
/// </summary>
/// <returns></returns>
QueryCompilerExecutor GetQueryCompilerExecutor();
bool IsEnumerableQuery();

View File

@ -12,14 +12,17 @@ using ShardingCore.ShardingExecutors;
namespace ShardingCore.Sharding.ShardingExecutors
{
public class DefaultShardingComplierExecutor: IShardingComplierExecutor
/// <summary>
/// 默认的分片编译执行者
/// </summary>
public class DefaultShardingCompilerExecutor: IShardingCompilerExecutor
{
private readonly ILogger<DefaultShardingComplierExecutor> _logger;
private readonly ILogger<DefaultShardingCompilerExecutor> _logger;
private readonly IShardingTrackQueryExecutor _shardingTrackQueryExecutor;
private readonly IQueryCompilerContextFactory _queryCompilerContextFactory;
private readonly IPrepareParser _prepareParser;
public DefaultShardingComplierExecutor(ILogger<DefaultShardingComplierExecutor> logger,
public DefaultShardingCompilerExecutor(ILogger<DefaultShardingCompilerExecutor> logger,
IShardingTrackQueryExecutor shardingTrackQueryExecutor, IQueryCompilerContextFactory queryCompilerContextFactory,IPrepareParser prepareParser)
{
_logger = logger;

View File

@ -22,6 +22,9 @@ namespace ShardingCore
* @Date: Saturday, 02 January 2021 19:37:27
* @Email: 326308290@qq.com
*/
/// <summary>
/// 分片容器全局唯一提供静态依赖注入<code>IServiceProvider</code>
/// </summary>
public class ShardingContainer
{
private ShardingContainer()
@ -45,14 +48,29 @@ namespace ShardingCore
serviceProvider = services;
}
/// <summary>
/// 获取服务
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T GetService<T>()
{
return ServiceProvider.GetService<T>();
}
/// <summary>
/// 获取服务集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<T> GetServices<T>()
{
return ServiceProvider.GetServices<T>();
}
/// <summary>
/// 根据类型获取服务
/// </summary>
/// <param name="serviceType"></param>
/// <returns></returns>
public static object GetService(Type serviceType)
{
return ServiceProvider.GetService(serviceType);