完成分库版本支持分页配置

This commit is contained in:
xuejiaming 2021-09-22 17:29:59 +08:00
parent 26f177aebb
commit ce30a09fb6
48 changed files with 980 additions and 190 deletions

View File

@ -12,7 +12,7 @@ namespace Sample.SqlServer.Shardings
public void Configure(PaginationBuilder<SysUserSalary> builder) public void Configure(PaginationBuilder<SysUserSalary> builder)
{ {
builder.PaginationSequence(o => o.Id) builder.PaginationSequence(o => o.Id)
.UseTailComparer(Comparer<string>.Default) .UseRouteComparer(Comparer<string>.Default)
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch); .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch);
builder.PaginationSequence(o => o.DateOfMonth) builder.PaginationSequence(o => o.DateOfMonth)
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone(10); .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone(10);

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ShardingCore.Core.QueryRouteManagers.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/22 7:54:11
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
/// <summary>
/// 路由断言
/// </summary>
public interface IDataSourceRouteAssert
{
/// <summary>
/// 断言路由结果
/// </summary>
/// <param name="allDataSources">所有的路由数据源</param>
/// <param name="resultDataSources">本次查询路由返回结果</param>
void Assert(List<string> allDataSources, List<string> resultDataSources);
}
public interface IDataSourceRouteAssert<T> : IDataSourceRouteAssert where T : class, IShardingDataSource
{
}
}

View File

@ -13,12 +13,12 @@ namespace ShardingCore.Core.QueryRouteManagers.Abstractions
/// <summary> /// <summary>
/// 路由断言 /// 路由断言
/// </summary> /// </summary>
public interface IRouteAssert public interface ITableRouteAssert
{ {
void Assert(List<IPhysicTable> allPhysicTables, List<IPhysicTable> resultPhysicTables); void Assert(List<IPhysicTable> allPhysicTables, List<IPhysicTable> resultPhysicTables);
} }
public interface IRouteAssert<T> : IRouteAssert where T : class, IShardingTable public interface ITableRouteAssert<T> : ITableRouteAssert where T : class,IShardingTable
{ {
} }

View File

@ -16,23 +16,43 @@ namespace ShardingCore.Core.QueryRouteManagers
*/ */
public class ShardingRouteContext public class ShardingRouteContext
{ {
#region
/// <summary> /// <summary>
/// 强制路由直接返回对应的后缀表 /// 强制路由直接返回对应的后缀表
/// </summary> /// </summary>
public Dictionary<Type, HashSet<string>> Must { get; } public Dictionary<Type, HashSet<string>> MustDataSource { get; }
/// <summary> /// <summary>
/// 提示路由会经过断言的强制路由 /// 提示路由会经过断言的强制路由
/// </summary> /// </summary>
public Dictionary<Type, HashSet<string>> Hint { get; } public Dictionary<Type, HashSet<string>> HintDataSource { get; }
/// <summary> /// <summary>
/// 断言 /// 断言
/// </summary> /// </summary>
public Dictionary<Type, LinkedList<IRouteAssert>> Assert { get; } public Dictionary<Type, LinkedList<IDataSourceRouteAssert>> AssertDataSource { get; }
#endregion
#region
/// <summary>
/// 强制路由直接返回对应的后缀表
/// </summary>
public Dictionary<Type, HashSet<string>> MustTable { get; }
/// <summary>
/// 提示路由会经过断言的强制路由
/// </summary>
public Dictionary<Type, HashSet<string>> HintTable { get; }
/// <summary>
/// 断言
/// </summary>
public Dictionary<Type, LinkedList<ITableRouteAssert>> AssertTable { get; }
#endregion
private ShardingRouteContext() private ShardingRouteContext()
{ {
Must = new Dictionary<Type, HashSet<string>>(); MustDataSource = new Dictionary<Type, HashSet<string>>();
Hint = new Dictionary<Type, HashSet<string>>(); HintDataSource = new Dictionary<Type, HashSet<string>>();
Assert = new Dictionary<Type, LinkedList<IRouteAssert>>(); AssertDataSource = new Dictionary<Type, LinkedList<IDataSourceRouteAssert>>();
MustTable = new Dictionary<Type, HashSet<string>>();
HintTable = new Dictionary<Type, HashSet<string>>();
AssertTable = new Dictionary<Type, LinkedList<ITableRouteAssert>>();
} }
public static ShardingRouteContext Create() public static ShardingRouteContext Create()

View File

@ -22,10 +22,11 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
where TShardingDbContext : DbContext, IShardingDbContext where TShardingDbContext : DbContext, IShardingDbContext
{ {
string DefaultDataSourceName { get; } string DefaultDataSourceName { get; }
/// <summary> /// <summary>
/// 路由到具体的物理数据源 /// 路由到具体的物理数据源
/// </summary> /// </summary>
/// <param name="entityType"></param>
/// <param name="routeRouteConfig"></param>
/// <returns>data source names</returns> /// <returns>data source names</returns>
List<string> RouteTo(Type entityType, ShardingDataSourceRouteConfig routeRouteConfig); List<string> RouteTo(Type entityType, ShardingDataSourceRouteConfig routeRouteConfig);

View File

@ -38,9 +38,9 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
var virtualDataSourceRoute = GetRoute( entityType); var virtualDataSourceRoute = GetRoute( entityType);
if (routeRouteConfig.UseQueryable()) if (routeRouteConfig.UseQueryable())
return virtualDataSourceRoute.RouteWithWhere(routeRouteConfig.GetQueryable()); return virtualDataSourceRoute.RouteWithPredicate(routeRouteConfig.GetQueryable(), true);
if (routeRouteConfig.UsePredicate()) if (routeRouteConfig.UsePredicate())
return virtualDataSourceRoute.RouteWithWhere((IQueryable)Activator.CreateInstance(typeof(EnumerableQuery<>).MakeGenericType(entityType), routeRouteConfig.UsePredicate())); return virtualDataSourceRoute.RouteWithPredicate((IQueryable)Activator.CreateInstance(typeof(EnumerableQuery<>).MakeGenericType(entityType), routeRouteConfig.UsePredicate()), false);
object shardingKeyValue = null; object shardingKeyValue = null;
if (routeRouteConfig.UseValue()) if (routeRouteConfig.UseValue())
shardingKeyValue = routeRouteConfig.GetShardingKeyValue(); shardingKeyValue = routeRouteConfig.GetShardingKeyValue();
@ -103,10 +103,10 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
public bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute) public bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute)
{ {
if (!virtualDataSourceRoute.EntityType.IsShardingDataSource()) if (!virtualDataSourceRoute.ShardingEntityType.IsShardingDataSource())
throw new InvalidOperationException($"{virtualDataSourceRoute.EntityType.FullName} should impl {nameof(IShardingDataSource)}"); throw new InvalidOperationException($"{virtualDataSourceRoute.ShardingEntityType.FullName} should impl {nameof(IShardingDataSource)}");
return _dataSourceVirtualRoutes.TryAdd(virtualDataSourceRoute.EntityType, virtualDataSourceRoute); return _dataSourceVirtualRoutes.TryAdd(virtualDataSourceRoute.ShardingEntityType, virtualDataSourceRoute);
} }
} }
} }

View File

@ -40,6 +40,7 @@ namespace ShardingCore.Core.VirtualTables
/// 分库配置 /// 分库配置
/// </summary> /// </summary>
public PaginationMetadata PaginationMetadata { get; } public PaginationMetadata PaginationMetadata { get; }
/// <summary> /// <summary>
/// 是否启用智能分页 /// 是否启用智能分页
/// </summary> /// </summary>
@ -54,7 +55,7 @@ namespace ShardingCore.Core.VirtualTables
EntityType = typeof(T); EntityType = typeof(T);
ShardingConfig = ShardingUtil.Parse(EntityType); ShardingConfig = ShardingUtil.Parse(EntityType);
var paginationConfiguration = virtualTableRoute.CreatePaginationConfiguration(); var paginationConfiguration = virtualTableRoute.CreatePaginationConfiguration();
if (paginationConfiguration != null) if (paginationConfiguration!=null)
{ {
PaginationMetadata = new PaginationMetadata(); PaginationMetadata = new PaginationMetadata();
var paginationBuilder = new PaginationBuilder<T>(PaginationMetadata); var paginationBuilder = new PaginationBuilder<T>(PaginationMetadata);

View File

@ -0,0 +1,107 @@
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/8/25 17:23:42
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
/// <summary>
/// 过滤虚拟路由用于处理强制路由、提示路由、路由断言
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
public abstract class AbstractShardingFilterVirtualDataSourceRoute<T, TKey> : AbstractVirtualDataSourceRoute<T, TKey> where T : class, IShardingDataSource
{
public ShardingRouteContext CurrentShardingRouteContext =>
ShardingContainer.GetService<IShardingRouteManager>().Current;
/// <summary>
/// 启用提示路由
/// </summary>
protected virtual bool EnableHintRoute => false;
/// <summary>
/// 启用断言路由
/// </summary>
protected virtual bool EnableAssertRoute => false;
public override List<string> RouteWithPredicate(IQueryable queryable,bool isQuery)
{
var allDataSourceNames = GetAllDataSourceNames();
if (!isQuery)
{
//后拦截器
return AfterDataSourceFilter(allDataSourceNames, DoRouteWithPredicate(allDataSourceNames, queryable));
}
//强制路由不经过断言
if (EnableHintRoute)
{
if (CurrentShardingRouteContext != null)
{
if (CurrentShardingRouteContext.TryGetMustDataSource<T>(out HashSet<string> mustDataSources) && mustDataSources.IsNotEmpty())
{
var dataSources = allDataSourceNames.Where(o => mustDataSources.Contains(o)).ToList();
if (dataSources.IsEmpty()||dataSources.Count!=mustDataSources.Count)
throw new ShardingCoreException(
$" sharding data source route must error:[{ShardingEntityType.FullName}]-->[{string.Join(",",mustDataSources)}]");
return dataSources;
}
if (CurrentShardingRouteContext.TryGetHintDataSource<T>(out HashSet<string> hintDataSouces) && hintDataSouces.IsNotEmpty())
{
var dataSources = allDataSourceNames.Where(o => hintDataSouces.Contains(o)).ToList();
if (dataSources.IsEmpty()||dataSources.Count!=hintDataSouces.Count)
throw new ShardingCoreException(
$" sharding data source route hint error:[{ShardingEntityType.FullName}]-->[{string.Join(",",hintDataSouces)}]");
ProcessAssertRoutes(allDataSourceNames, dataSources);
return dataSources;
}
}
}
var filterDataSources = DoRouteWithPredicate(allDataSourceNames, queryable);
//后拦截器
var resultDataSources = AfterDataSourceFilter(allDataSourceNames, filterDataSources);
//最后处理断言
ProcessAssertRoutes(allDataSourceNames, resultDataSources);
return resultDataSources;
}
private void ProcessAssertRoutes(List<string> allDataSources,List<string> filterDataSources)
{
if (EnableAssertRoute)
{
if (CurrentShardingRouteContext != null && CurrentShardingRouteContext.TryGetAssertDataSource<T>(out ICollection<IDataSourceRouteAssert> routeAsserts) && routeAsserts.IsNotEmpty())
{
foreach (var routeAssert in routeAsserts)
{
routeAssert.Assert(allDataSources, filterDataSources);
}
}
}
}
protected abstract List<string> DoRouteWithPredicate(List<string> allDataSourceNames, IQueryable queryable);
/// <summary>
/// 物理表过滤后
/// </summary>
/// <param name="allDataSourceNames">所有的物理表</param>
/// <param name="filterDataSources">过滤后的物理表</param>
/// <returns></returns>
protected virtual List<string> AfterDataSourceFilter(List<string> allDataSourceNames, List<string> filterDataSources)
{
return filterDataSources;
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Utils;
namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Saturday, 19 December 2020 19:55:24
* @Email: 326308290@qq.com
*/
/// <summary>
/// 抽象类型抽象出对应的条件表达式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
public abstract class AbstractShardingOperatorVirtualDataSourceRoute<T, TKey> : AbstractShardingFilterVirtualDataSourceRoute<T, TKey> where T : class, IShardingDataSource
{
protected override List<string> DoRouteWithPredicate(List<string> allDataSourceNames, IQueryable queryable)
{
//获取所有需要路由的表后缀
var filter = ShardingUtil.GetRouteShardingTableFilter(queryable, ShardingUtil.Parse(typeof(T)), ConvertToShardingKey, GetRouteToFilter);
var dataSources = allDataSourceNames.Where(o => filter(o)).ToList();
return dataSources;
}
/// <summary>
/// 如何路由到具体表 shardingKeyValue:分表的值, 返回结果:如果返回true表示返回该表 第一个参数 tail 第二参数是否返回该物理表
/// </summary>
/// <param name="shardingKey">分表的值</param>
/// <param name="shardingOperator">操作</param>
/// <returns>如果返回true表示返回该表 第一个参数 tail 第二参数是否返回该物理表</returns>
protected abstract Expression<Func<string, bool>> GetRouteToFilter(TKey shardingKey, ShardingOperatorEnum shardingOperator);
public override string RouteWithValue(object shardingKey)
{
var allDataSourceNames = GetAllDataSourceNames();
var shardingKeyToDataSource = ShardingKeyToDataSourceName(shardingKey);
var dataSources = allDataSourceNames.Where(o => o== shardingKeyToDataSource).ToList();
if (dataSources.IsEmpty())
{
var routeConfig = ShardingUtil.Parse(typeof(T));
throw new ShardingKeyRouteNotMatchException($"{routeConfig.EntityType} -> [{routeConfig.ShardingTableField}] ->【{shardingKey}】 all data sources ->[{string.Join(",", allDataSourceNames.Select(o=>o))}]");
}
if (dataSources.Count > 1)
throw new ShardingKeyRouteMoreException($"data source:{string.Join(",", dataSources.Select(o => $"[{o}]"))}");
return dataSources[0];
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Sharding.PaginationConfigurations;
namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 18 December 2020 14:33:01
* @Email: 326308290@qq.com
*/
public abstract class AbstractVirtualDataSourceRoute<T, TKey> : IVirtualDataSourceRoute<T> where T : class, IShardingDataSource
{
public void Init()
{
var paginationConfiguration = CreatePaginationConfiguration();
if (paginationConfiguration != null)
{
PaginationMetadata = new PaginationMetadata();
var paginationBuilder = new PaginationBuilder<T>(PaginationMetadata);
paginationConfiguration.Configure(paginationBuilder);
}
}
public virtual IPaginationConfiguration<T> CreatePaginationConfiguration()
{
return null;
}
/// <summary>
/// entity type
/// </summary>
public Type ShardingEntityType => typeof(T);
public new PaginationMetadata PaginationMetadata { get; protected set; }
public bool EnablePagination => PaginationMetadata != null;
/// <summary>
/// 分库字段object类型的如何转成对应的泛型类型how convert sharding key to generic type key value
/// </summary>
/// <param name="shardingKey"></param>
/// <returns></returns>
protected abstract TKey ConvertToShardingKey(object shardingKey);
/// <summary>
/// 分库字段如何转成对应的数据源名称 how convert sharding data source key to data source name
/// </summary>
/// <param name="shardingKey"></param>
/// <returns></returns>
public abstract string ShardingKeyToDataSourceName(object shardingKey);
/// <summary>
/// 根据表达式返回对应的数据源名称 find data source names with queryable
/// </summary>
/// <param name="queryable"></param>
/// <param name="isQuery"></param>
/// <returns></returns>
public abstract List<string> RouteWithPredicate(IQueryable queryable, bool isQuery);
/// <summary>
/// 值如何转成对应的数据源
/// </summary>
/// <param name="shardingKey"></param>
/// <returns></returns>
public abstract string RouteWithValue(object shardingKey);
public abstract List<string> GetAllDataSourceNames();
public abstract bool AddDataSourceName(string dataSourceName);
}
}

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
using ShardingCore.Sharding.PaginationConfigurations;
namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes
{ {
@ -13,15 +14,24 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes
*/ */
public interface IVirtualDataSourceRoute public interface IVirtualDataSourceRoute
{ {
Type EntityType { get; } Type ShardingEntityType { get;}
/// <summary>
/// 分页配置
/// </summary>
PaginationMetadata PaginationMetadata { get; }
/// <summary>
/// 是否启用分页配置
/// </summary>
bool EnablePagination { get; }
string ShardingKeyToDataSourceName(object shardingKeyValue); string ShardingKeyToDataSourceName(object shardingKeyValue);
/// <summary> /// <summary>
/// 根据查询条件路由返回物理数据源 /// 根据查询条件路由返回物理数据源
/// </summary> /// </summary>
/// <param name="queryable"></param> /// <param name="queryable"></param>
/// <param name="isQuery"></param>
/// <returns>data source name</returns> /// <returns>data source name</returns>
List<string> RouteWithWhere(IQueryable queryable); List<string> RouteWithPredicate(IQueryable queryable, bool isQuery);
/// <summary> /// <summary>
/// 根据值进行路由 /// 根据值进行路由
@ -31,10 +41,25 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes
string RouteWithValue(object shardingKeyValue); string RouteWithValue(object shardingKeyValue);
List<string> GetAllDataSourceNames(); List<string> GetAllDataSourceNames();
/// <summary>
/// 添加数据源
/// </summary>
/// <param name="dataSourceName"></param>
/// <returns></returns>
bool AddDataSourceName(string dataSourceName);
/// <summary>
/// 初始化
/// </summary>
void Init();
} }
public interface IVirtualDataSourceRoute<T> : IVirtualDataSourceRoute where T : class public interface IVirtualDataSourceRoute<T> : IVirtualDataSourceRoute where T : class, IShardingDataSource
{ {
/// <summary>
/// 返回null就是表示不开启分页配置
/// </summary>
/// <returns></returns>
IPaginationConfiguration<T> CreatePaginationConfiguration();
} }
} }

View File

@ -81,7 +81,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{ {
if (EnableAssertRoute) if (EnableAssertRoute)
{ {
if (CurrentShardingRouteContext != null && CurrentShardingRouteContext.TryGetAssertTail<T>(out ICollection<IRouteAssert> routeAsserts) && routeAsserts.IsNotEmpty()) if (CurrentShardingRouteContext != null && CurrentShardingRouteContext.TryGetAssertTail<T>(out ICollection<ITableRouteAssert> routeAsserts) && routeAsserts.IsNotEmpty())
{ {
foreach (var routeAssert in routeAsserts) foreach (var routeAssert in routeAsserts)
{ {

View File

@ -38,7 +38,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
public override IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey) public override IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey)
{ {
var shardingKeyToTail = ShardingKeyToTail(ConvertToShardingKey(shardingKey)); var shardingKeyToTail = ShardingKeyToTail(shardingKey);
var physicTables = allPhysicTables.Where(o => o.Tail== shardingKeyToTail).ToList(); var physicTables = allPhysicTables.Where(o => o.Tail== shardingKeyToTail).ToList();
if (physicTables.IsEmpty()) if (physicTables.IsEmpty())

View File

@ -51,9 +51,9 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
/// 根据值路由 /// 根据值路由
/// </summary> /// </summary>
/// <param name="allPhysicTables"></param> /// <param name="allPhysicTables"></param>
/// <param name="shardingKeyValue"></param> /// <param name="shardingKey"></param>
/// <returns></returns> /// <returns></returns>
public abstract IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKeyValue); public abstract IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey);
/// <summary> /// <summary>
/// 返回数据库现有的尾巴 /// 返回数据库现有的尾巴
/// </summary> /// </summary>

View File

@ -33,9 +33,9 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes
/// 根据值进行路由 /// 根据值进行路由
/// </summary> /// </summary>
/// <param name="allPhysicTables"></param> /// <param name="allPhysicTables"></param>
/// <param name="shardingKeyValue"></param> /// <param name="shardingKey"></param>
/// <returns></returns> /// <returns></returns>
IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKeyValue); IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey);
/// <summary> /// <summary>
/// 获取所有的目前数据库存在的尾巴 /// 获取所有的目前数据库存在的尾巴
/// get all tails in the db /// get all tails in the db

View File

@ -25,5 +25,15 @@ namespace ShardingCore.Extensions.InternalExtensions
{ {
return condition ? source.OrderByDescending(keySelector, comparer) : source; return condition ? source.OrderByDescending(keySelector, comparer) : source;
} }
public static IOrderedEnumerable<TShource> ThenByIf<TShource, TKey>(this IOrderedEnumerable<TShource> source, Func<TShource, TKey> keySelector, bool condition,
IComparer<TKey>? comparer)
{
return condition ? source.ThenBy(keySelector, comparer) : source;
}
public static IOrderedEnumerable<TShource> ThenByDescendingIf<TShource, TKey>(this IOrderedEnumerable<TShource> source, Func<TShource, TKey> keySelector, bool condition,
IComparer<TKey>? comparer)
{
return condition ? source.ThenByDescending(keySelector, comparer) : source;
}
} }
} }

View File

@ -0,0 +1,201 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShardingCore.Core;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Exceptions;
namespace ShardingCore.Extensions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/8/23 22:19:24
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public static class ShardingDataSourceRouteExtension
{
/// <summary>
/// 创建或者添加强制路由
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="shardingRouteContext"></param>
/// <param name="dataSources"></param>
/// <returns>任何一个dataSources被添加成功就返回成功</returns>
public static bool TryCreateOrAddMustDataSource<TEntity>(this ShardingRouteContext shardingRouteContext, params string[] dataSources) where TEntity : class, IShardingDataSource
{
return TryCreateOrAddMustDataSource(shardingRouteContext, typeof(TEntity), dataSources);
}
/// <summary>
/// 创建或者添加强制路由
/// </summary>
/// <param name="shardingRouteContext"></param>
/// <param name="entityType"></param>
/// <param name="dataSources"></param>
/// <returns>任何一个dataSources被添加成功就返回成功</returns>
public static bool TryCreateOrAddMustDataSource(this ShardingRouteContext shardingRouteContext, Type entityType, params string[] dataSources)
{
if (shardingRouteContext == null)
{
return false;
}
if (dataSources.IsEmpty())
return false;
if (!entityType.IsShardingDataSource())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingDataSource)}");
if (!shardingRouteContext.MustDataSource.TryGetValue(entityType,out HashSet<string> mustDataSources))
{
mustDataSources = new HashSet<string>();
shardingRouteContext.MustDataSource.Add(entityType, mustDataSources);
}
return dataSources.Select(o => mustDataSources.Add(o)).Any(o => o);
}
/// <summary>
/// 创建或者添加提示路由
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="shardingRouteContext"></param>
/// <param name="dataSources"></param>
/// <returns>任何一个dataSources被添加成功就返回成功</returns>
public static bool TryCreateOrAddHintDataSource<TEntity>(this ShardingRouteContext shardingRouteContext, params string[] dataSources) where TEntity : class, IShardingDataSource
{
return TryCreateOrAddHintDataSource(shardingRouteContext, typeof(TEntity), dataSources);
}
/// <summary>
/// 创建或者添加提示路由
/// </summary>
/// <param name="shardingRouteContext"></param>
/// <param name="entityType"></param>
/// <param name="dataSources"></param>
/// <returns>任何一个dataSources被添加成功就返回成功</returns>
public static bool TryCreateOrAddHintDataSource(this ShardingRouteContext shardingRouteContext, Type entityType, params string[] dataSources)
{
if (shardingRouteContext == null)
{
return false;
}
if (dataSources.IsEmpty())
return false;
if (!entityType.IsShardingDataSource())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingDataSource)}");
if (!shardingRouteContext.HintDataSource.TryGetValue(entityType, out HashSet<string> hintDataSources))
{
hintDataSources = new HashSet<string>();
shardingRouteContext.HintDataSource.Add(entityType, hintDataSources);
}
return dataSources.Select(o => hintDataSources.Add(o)).Any(o => o);
}
/// <summary>
/// 创建或者添加断言
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="shardingRouteContext"></param>
/// <param name="dataSources"></param>
/// <returns></returns>
public static bool TryCreateOrAddAssertDataSource<TEntity>(this ShardingRouteContext shardingRouteContext, params IDataSourceRouteAssert<TEntity>[] dataSources) where TEntity : class, IShardingDataSource
{
return TryCreateOrAddAssertDataSource(shardingRouteContext, typeof(TEntity), dataSources);
}
public static bool TryCreateOrAddAssertDataSource(this ShardingRouteContext shardingRouteContext, Type entityType, params IDataSourceRouteAssert[] asserts)
{
if (shardingRouteContext == null)
{
return false;
}
if (asserts.IsEmpty())
return false;
if (!entityType.IsShardingDataSource())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingDataSource)}");
if (!shardingRouteContext.AssertDataSource.TryGetValue(entityType, out LinkedList<IDataSourceRouteAssert> routeAsserts))
{
routeAsserts = new LinkedList<IDataSourceRouteAssert>();
shardingRouteContext.AssertDataSource.Add(entityType, routeAsserts);
}
foreach (var routeAssert in asserts)
{
routeAsserts.AddLast(routeAssert);
}
return true;
}
public static bool TryGetMustDataSource<TEntity>(this ShardingRouteContext shardingRouteContext, out HashSet<string> dataSources) where TEntity : class, IShardingDataSource
{
return TryGetMustDataSource(shardingRouteContext,typeof(TEntity),out dataSources);
}
public static bool TryGetMustDataSource(this ShardingRouteContext shardingRouteContext,Type entityType, out HashSet<string> dataSources)
{
if (shardingRouteContext == null)
{
dataSources = null;
return false;
}
if (!entityType.IsShardingDataSource())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingDataSource)}");
if (!shardingRouteContext.MustDataSource.ContainsKey(entityType))
{
dataSources = null;
return false;
}
dataSources = shardingRouteContext.MustDataSource[entityType];
return true;
}
public static bool TryGetHintDataSource<TEntity>(this ShardingRouteContext shardingRouteContext, out HashSet<string> dataSources) where TEntity : class,IShardingDataSource
{
return TryGetHintDataSource(shardingRouteContext,typeof(TEntity),out dataSources);
}
public static bool TryGetHintDataSource(this ShardingRouteContext shardingRouteContext,Type entityType, out HashSet<string> dataSources)
{
if (shardingRouteContext == null)
{
dataSources = null;
return false;
}
if (!entityType.IsShardingDataSource())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingDataSource)}");
if (!shardingRouteContext.HintDataSource.ContainsKey(entityType))
{
dataSources = null;
return false;
}
dataSources = shardingRouteContext.HintDataSource[entityType];
return true;
}
public static bool TryGetAssertDataSource<TEntity>(this ShardingRouteContext shardingRouteContext, out ICollection<IDataSourceRouteAssert> dataSources)where TEntity : class,IShardingDataSource
{
return TryGetAssertDataSource(shardingRouteContext,typeof(TEntity), out dataSources);
}
public static bool TryGetAssertDataSource(this ShardingRouteContext shardingRouteContext,Type entityType, out ICollection<IDataSourceRouteAssert> dataSources)
{
if (shardingRouteContext == null)
{
dataSources = null;
return false;
}
if (!entityType.IsShardingDataSource())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingDataSource)}");
if (!shardingRouteContext.AssertDataSource.ContainsKey(entityType))
{
dataSources = null;
return false;
}
dataSources = shardingRouteContext.AssertDataSource[entityType];
return true;
}
}
}

View File

@ -16,7 +16,7 @@ namespace ShardingCore.Extensions
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public static class ShardingRouteExtension public static class ShardingTableRouteExtension
{ {
/// <summary> /// <summary>
/// 创建或者添加强制路由 /// 创建或者添加强制路由
@ -47,10 +47,10 @@ namespace ShardingCore.Extensions
return false; return false;
if (!entityType.IsShardingTable()) if (!entityType.IsShardingTable())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}"); throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}");
if (!shardingRouteContext.Must.TryGetValue(entityType,out HashSet<string> mustTails)) if (!shardingRouteContext.MustTable.TryGetValue(entityType,out HashSet<string> mustTails))
{ {
mustTails = new HashSet<string>(); mustTails = new HashSet<string>();
shardingRouteContext.Must.Add(entityType, mustTails); shardingRouteContext.MustTable.Add(entityType, mustTails);
} }
return tails.Select(o => mustTails.Add(o)).Any(o => o); return tails.Select(o => mustTails.Add(o)).Any(o => o);
@ -84,10 +84,10 @@ namespace ShardingCore.Extensions
return false; return false;
if (!entityType.IsShardingTable()) if (!entityType.IsShardingTable())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}"); throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}");
if (!shardingRouteContext.Hint.TryGetValue(entityType, out HashSet<string> hintTails)) if (!shardingRouteContext.HintTable.TryGetValue(entityType, out HashSet<string> hintTails))
{ {
hintTails = new HashSet<string>(); hintTails = new HashSet<string>();
shardingRouteContext.Hint.Add(entityType, hintTails); shardingRouteContext.HintTable.Add(entityType, hintTails);
} }
return tails.Select(o => hintTails.Add(o)).Any(o => o); return tails.Select(o => hintTails.Add(o)).Any(o => o);
@ -99,11 +99,11 @@ namespace ShardingCore.Extensions
/// <param name="shardingRouteContext"></param> /// <param name="shardingRouteContext"></param>
/// <param name="tails"></param> /// <param name="tails"></param>
/// <returns></returns> /// <returns></returns>
public static bool TryCreateOrAddAssertTail<TEntity>(this ShardingRouteContext shardingRouteContext, params IRouteAssert<TEntity>[] tails) where TEntity : class, IShardingTable public static bool TryCreateOrAddAssertTail<TEntity>(this ShardingRouteContext shardingRouteContext, params ITableRouteAssert<TEntity>[] tails) where TEntity : class, IShardingTable
{ {
return TryCreateOrAddAssertTail(shardingRouteContext, typeof(TEntity), tails); return TryCreateOrAddAssertTail(shardingRouteContext, typeof(TEntity), tails);
} }
public static bool TryCreateOrAddAssertTail(this ShardingRouteContext shardingRouteContext, Type entityType, params IRouteAssert[] asserts) public static bool TryCreateOrAddAssertTail(this ShardingRouteContext shardingRouteContext, Type entityType, params ITableRouteAssert[] asserts)
{ {
if (shardingRouteContext == null) if (shardingRouteContext == null)
{ {
@ -114,10 +114,10 @@ namespace ShardingCore.Extensions
return false; return false;
if (!entityType.IsShardingTable()) if (!entityType.IsShardingTable())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}"); throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}");
if (!shardingRouteContext.Assert.TryGetValue(entityType, out LinkedList<IRouteAssert> routeAsserts)) if (!shardingRouteContext.AssertTable.TryGetValue(entityType, out LinkedList<ITableRouteAssert> routeAsserts))
{ {
routeAsserts = new LinkedList<IRouteAssert>(); routeAsserts = new LinkedList<ITableRouteAssert>();
shardingRouteContext.Assert.Add(entityType, routeAsserts); shardingRouteContext.AssertTable.Add(entityType, routeAsserts);
} }
foreach (var routeAssert in asserts) foreach (var routeAssert in asserts)
{ {
@ -142,13 +142,13 @@ namespace ShardingCore.Extensions
} }
if (!entityType.IsShardingTable()) if (!entityType.IsShardingTable())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}"); throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}");
if (!shardingRouteContext.Must.ContainsKey(entityType)) if (!shardingRouteContext.MustTable.ContainsKey(entityType))
{ {
tail = null; tail = null;
return false; return false;
} }
tail = shardingRouteContext.Must[entityType]; tail = shardingRouteContext.MustTable[entityType];
return true; return true;
} }
public static bool TryGetHintTail<TEntity>(this ShardingRouteContext shardingRouteContext, out HashSet<string> tail) where TEntity : class,IShardingTable public static bool TryGetHintTail<TEntity>(this ShardingRouteContext shardingRouteContext, out HashSet<string> tail) where TEntity : class,IShardingTable
@ -164,21 +164,21 @@ namespace ShardingCore.Extensions
} }
if (!entityType.IsShardingTable()) if (!entityType.IsShardingTable())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}"); throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}");
if (!shardingRouteContext.Hint.ContainsKey(entityType)) if (!shardingRouteContext.HintTable.ContainsKey(entityType))
{ {
tail = null; tail = null;
return false; return false;
} }
tail = shardingRouteContext.Hint[entityType]; tail = shardingRouteContext.HintTable[entityType];
return true; return true;
} }
public static bool TryGetAssertTail<TEntity>(this ShardingRouteContext shardingRouteContext, out ICollection<IRouteAssert> tail)where TEntity : class,IShardingTable public static bool TryGetAssertTail<TEntity>(this ShardingRouteContext shardingRouteContext, out ICollection<ITableRouteAssert> tail)where TEntity : class,IShardingTable
{ {
return TryGetAssertTail(shardingRouteContext,typeof(TEntity), out tail); return TryGetAssertTail(shardingRouteContext,typeof(TEntity), out tail);
} }
public static bool TryGetAssertTail(this ShardingRouteContext shardingRouteContext,Type entityType, out ICollection<IRouteAssert> tail) public static bool TryGetAssertTail(this ShardingRouteContext shardingRouteContext,Type entityType, out ICollection<ITableRouteAssert> tail)
{ {
if (shardingRouteContext == null) if (shardingRouteContext == null)
{ {
@ -187,13 +187,13 @@ namespace ShardingCore.Extensions
} }
if (!entityType.IsShardingTable()) if (!entityType.IsShardingTable())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}"); throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}");
if (!shardingRouteContext.Assert.ContainsKey(entityType)) if (!shardingRouteContext.AssertTable.ContainsKey(entityType))
{ {
tail = null; tail = null;
return false; return false;
} }
tail = shardingRouteContext.Assert[entityType]; tail = shardingRouteContext.AssertTable[entityType];
return true; return true;
} }

View File

@ -19,19 +19,45 @@ namespace ShardingCore.Extensions
/// <param name="streamMergeContext"></param> /// <param name="streamMergeContext"></param>
/// <typeparam name="TEntity"></typeparam> /// <typeparam name="TEntity"></typeparam>
/// <returns></returns> /// <returns></returns>
public static bool IsShardingQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext) public static bool IsNormalQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
{ {
return streamMergeContext.TableRouteResults.Count() > 1; return streamMergeContext.QueryEntities.Any(o=>!o.IsShardingDataSource()&&!o.IsShardingTable());
} }
/// <summary>
/// 单路由查询
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="streamMergeContext"></param>
/// <returns></returns>
public static bool IsSingleRouteQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
{
return streamMergeContext.DataSourceRouteResult.IntersectDataSources.Count==1&&streamMergeContext.TableRouteResults.Count()==1;
}
/// <summary>
/// 单表查询
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="streamMergeContext"></param>
/// <returns></returns>
public static bool IsSingleShardingTableQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext) public static bool IsSingleShardingTableQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
{ {
return streamMergeContext.TableRouteResults.First().ReplaceTables.Count(o => o.EntityType.IsShardingTable()) == 1; return streamMergeContext.TableRouteResults.First().ReplaceTables.Count(o => o.EntityType.IsShardingTable()) == 1;
} }
/// <summary>
public static IVirtualTableManager GetVirtualTableManager<TEntity>(this StreamMergeContext<TEntity> streamMergeContext) /// 本次查询仅包含一个对象的分表分库
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="streamMergeContext"></param>
/// <returns></returns>
public static bool IsSingleShardingQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
{ {
return (IVirtualTableManager)ShardingContainer.GetService( return streamMergeContext.GetOriginalQueryable().ParseQueryableRoute().Count(o=>o.IsShardingTable()||o.IsShardingDataSource())==1;
typeof(IVirtualTableManager<>).GetGenericType0(streamMergeContext.GetShardingDbContext().GetType())); }
public static bool IsSupportPaginationQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
{
var queryEntities = streamMergeContext.GetOriginalQueryable().ParseQueryableRoute();
//仅一个对象支持分库或者分表的组合
return queryEntities.Count(o=>(o.IsShardingDataSource()&&!o.IsShardingTable()) ||(o.IsShardingDataSource()&& o.IsShardingTable())|| (!o.IsShardingDataSource() && o.IsShardingTable())) ==1;
} }
} }
} }

View File

@ -12,7 +12,7 @@ namespace ShardingCore.Sharding.PaginationConfigurations
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public interface IPaginationConfiguration<TEntity> where TEntity : class,IShardingTable public interface IPaginationConfiguration<TEntity> where TEntity : class
{ {
void Configure(PaginationBuilder<TEntity> builder); void Configure(PaginationBuilder<TEntity> builder);
} }

View File

@ -23,12 +23,12 @@ namespace ShardingCore.Sharding.PaginationConfigurations
/// <summary> /// <summary>
/// 使用哪个后缀比较 /// 使用哪个后缀比较
/// </summary> /// </summary>
/// <param name="tailComparer"></param> /// <param name="routeComparer"></param>
/// <returns></returns> /// <returns></returns>
public PaginationOrderPropertyBuilder UseTailComparer(IComparer<string> tailComparer) public PaginationOrderPropertyBuilder UseRouteComparer(IComparer<string> routeComparer)
{ {
_paginationSequenceConfig.TailComparer= tailComparer ?? throw new ArgumentException(nameof(tailComparer)); _paginationSequenceConfig.RouteComparer= routeComparer ?? throw new ArgumentException(nameof(routeComparer));
return this; return this;
} }
/// <summary> /// <summary>
@ -45,10 +45,12 @@ namespace ShardingCore.Sharding.PaginationConfigurations
/// 如果查询没发现排序就将当前配置追加上去 /// 如果查询没发现排序就将当前配置追加上去
/// </summary> /// </summary>
/// <param name="order">大于等于0生效,越大优先级越高</param> /// <param name="order">大于等于0生效,越大优先级越高</param>
/// <param name="defAsc">默认asc还是desc</param>
/// <returns></returns> /// <returns></returns>
public PaginationOrderPropertyBuilder UseAppendIfOrderNone(int order=0) public PaginationOrderPropertyBuilder UseAppendIfOrderNone(int order=0,bool defAsc=true)
{ {
_paginationSequenceConfig.AppendOrder = order; _paginationSequenceConfig.AppendOrder = order;
_paginationSequenceConfig.AppendAsc = defAsc;
return this; return this;
} }
} }

View File

@ -17,16 +17,16 @@ namespace ShardingCore.Sharding.PaginationConfigurations
*/ */
public class PaginationSequenceConfig public class PaginationSequenceConfig
{ {
public PaginationSequenceConfig(LambdaExpression orderPropertyExpression, PaginationMatchEnum paginationMatchEnum= PaginationMatchEnum.Owner, IComparer<string> tailComparer=null) public PaginationSequenceConfig(LambdaExpression orderPropertyExpression, PaginationMatchEnum paginationMatchEnum= PaginationMatchEnum.Owner, IComparer<string> routeComparer=null)
{ {
OrderPropertyInfo = orderPropertyExpression.GetPropertyAccess(); OrderPropertyInfo = orderPropertyExpression.GetPropertyAccess();
PropertyName = OrderPropertyInfo.Name; PropertyName = OrderPropertyInfo.Name;
PaginationMatchEnum = paginationMatchEnum; PaginationMatchEnum = paginationMatchEnum;
TailComparer = tailComparer ?? Comparer<string>.Default; RouteComparer = routeComparer ?? Comparer<string>.Default;
SequenceTails = new HashSet<string>(); SequenceTails = new HashSet<string>();
} }
public IComparer<string> TailComparer { get; set; } public IComparer<string> RouteComparer { get; set; }
public PaginationMatchEnum PaginationMatchEnum { get; set; } public PaginationMatchEnum PaginationMatchEnum { get; set; }
public PropertyInfo OrderPropertyInfo { get; set; } public PropertyInfo OrderPropertyInfo { get; set; }
@ -38,6 +38,8 @@ namespace ShardingCore.Sharding.PaginationConfigurations
/// 大于等于0表示需要 /// 大于等于0表示需要
/// </summary> /// </summary>
public int AppendOrder { get; set; } = -1; public int AppendOrder { get; set; } = -1;
public bool AppendAsc { get; set; } = true;
public string PropertyName { get;} public string PropertyName { get;}
public ISet<string> SequenceTails { get; } public ISet<string> SequenceTails { get; }

View File

@ -138,8 +138,8 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors
var streamMergeContext = streamMergeContextMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamMergeContextFactory, new[] { queryable, shardingDbContext }); var streamMergeContext = streamMergeContextMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamMergeContextFactory, new[] { queryable, shardingDbContext });
Type streamMergeEngineType = typeof(AsyncEnumerableStreamMergeEngine<>); Type streamMergeEngineType = typeof(AsyncEnumerableStreamMergeEngine<,>);
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType); streamMergeEngineType = streamMergeEngineType.MakeGenericType(shardingDbContext.GetType(), queryEntityType);
return (TResult)Activator.CreateInstance(streamMergeEngineType, streamMergeContext); return (TResult)Activator.CreateInstance(streamMergeEngineType, streamMergeContext);
} }

View File

@ -4,10 +4,15 @@ using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ShardingCore.Core.Internal.Visitors; using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Core.ShardingPage.Abstractions; using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualTables; using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
using ShardingCore.Core.VirtualTables; using ShardingCore.Core.VirtualTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions; using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -25,89 +30,192 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class EnumeratorShardingQueryExecutor<TEntity> public class EnumeratorShardingQueryExecutor<TShardingDbContext, TEntity>
where TShardingDbContext : DbContext, IShardingDbContext
{ {
private readonly StreamMergeContext<TEntity> _streamMergeContext; private readonly StreamMergeContext<TEntity> _streamMergeContext;
private readonly IShardingPageManager _shardingPageManager; private readonly IShardingPageManager _shardingPageManager;
private readonly IVirtualTableManager _virtualTableManager; private readonly IVirtualTableManager<TShardingDbContext> _virtualTableManager;
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
public EnumeratorShardingQueryExecutor(StreamMergeContext<TEntity> streamMergeContext) public EnumeratorShardingQueryExecutor(StreamMergeContext<TEntity> streamMergeContext)
{ {
_streamMergeContext = streamMergeContext; _streamMergeContext = streamMergeContext;
_shardingPageManager = ShardingContainer.GetService<IShardingPageManager>(); _shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
_virtualTableManager = streamMergeContext.GetVirtualTableManager(); _virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDbContext>>();
_virtualDataSource = ShardingContainer.GetService<IVirtualDataSource<TShardingDbContext>>();
} }
public IEnumeratorStreamMergeEngine<TEntity> ExecuteAsync(CancellationToken cancellationToken = new CancellationToken()) public IEnumeratorStreamMergeEngine<TEntity> ExecuteAsync(CancellationToken cancellationToken = new CancellationToken())
{ {
//操作单表 //操作单表或者单分库分表之类的
if (!_streamMergeContext.IsShardingQuery()) if (_streamMergeContext.IsNormalQuery()||_streamMergeContext.IsSingleRouteQuery())
{ {
return new SingleQueryEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext); return new SingleQueryEnumeratorAsyncStreamMergeEngine<TShardingDbContext, TEntity>(_streamMergeContext);
} }
//未开启系统分表或者本次查询涉及多张分表 //未开启系统分表或者本次查询涉及多张分表
if (_streamMergeContext.IsPaginationQuery() && _streamMergeContext.IsSingleShardingTableQuery() && _shardingPageManager.Current != null) if (_streamMergeContext.IsPaginationQuery() && _streamMergeContext.IsSupportPaginationQuery() && _shardingPageManager.Current != null)
{ {
//获取虚拟表判断是否启用了分页配置 //获取虚拟表判断是否启用了分页配置
var shardingEntityType = _streamMergeContext.TableRouteResults.First().ReplaceTables.First().EntityType; var shardingEntityType = _streamMergeContext.QueryEntities.FirstOrDefault(o => o.IsShardingDataSource() || o.IsShardingTable());
var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntityType); if (shardingEntityType == null)
if (virtualTable.EnablePagination) throw new ShardingCoreException($"query not found sharding data source or sharding table entity");
if (_streamMergeContext.Orders.IsEmpty())
{ {
var paginationMetadata = virtualTable.PaginationMetadata; //自动添加属性顺序排序
//判断本次查询的排序是否包含order如果不包含就获取默认添加的排序 //除了判断属性名还要判断所属关系
if (_streamMergeContext.Orders.IsEmpty()) var mergeEngine = DoNoOrderAppendEnumeratorStreamMergeEngine(shardingEntityType);
{ if (mergeEngine != null)
//除了判断属性名还要判断所属关系 return mergeEngine;
var appendPaginationConfig = paginationMetadata.PaginationConfigs.OrderByDescending(o => o.AppendOrder) }
.FirstOrDefault(o => o.AppendIfOrderNone && typeof(TEntity).ContainPropertyName(o.PropertyName) && PaginationMatch(o)); else
if (appendPaginationConfig != null) {
{ var mergeEngine = DoOrderSequencePaginationEnumeratorStreamMergeEngine(shardingEntityType);
return new AppenOrderSequenceEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext, appendPaginationConfig, _shardingPageManager.Current.RouteQueryResults);
}
}
else
{
var orderCount = _streamMergeContext.Orders.Count();
var primaryOrder = _streamMergeContext.Orders.First();
if (orderCount == 1)
{
var sequenceFullMatchOrderConfig = paginationMetadata.PaginationConfigs.Where(o => !o.PaginationMatchEnum.HasFlag(PaginationMatchEnum.PrimaryMatch)).FirstOrDefault(o => PaginationPrimaryMatch(o, primaryOrder));
if (sequenceFullMatchOrderConfig != null)
{
return new SequenceEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext, sequenceFullMatchOrderConfig, _shardingPageManager.Current.RouteQueryResults, primaryOrder.IsAsc);
}
}
var sequencePrimaryMatchOrderConfig = paginationMetadata.PaginationConfigs.Where(o => o.PaginationMatchEnum.HasFlag(PaginationMatchEnum.PrimaryMatch)).FirstOrDefault(o => PaginationPrimaryMatch(o, primaryOrder)); if (mergeEngine != null)
if (sequencePrimaryMatchOrderConfig != null) return mergeEngine;
{
return new SequenceEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext, sequencePrimaryMatchOrderConfig, _shardingPageManager.Current.RouteQueryResults, primaryOrder.IsAsc);
}
//skip过大reserve skip
if (paginationMetadata.EnableReverseShardingPage && _streamMergeContext.Take.GetValueOrDefault() > 0)
{
var total = _shardingPageManager.Current.RouteQueryResults.Sum(o => o.QueryResult);
if (paginationMetadata.IsUseReverse(_streamMergeContext.Skip.GetValueOrDefault(), total))
{
return new ReverseShardingEnumeratorAsyncStreamMergeEngine<TEntity>( _streamMergeContext, total);
}
}
//if (paginationMetadata.EnableUnevenShardingPage) //if (paginationMetadata.EnableUnevenShardingPage)
//{ //{
// if (paginationMetadata.IsUseUneven(_shardingPageManager.Current.RouteQueryResults, _streamMergeContext.Skip.GetValueOrDefault())) // if (paginationMetadata.IsUseUneven(_shardingPageManager.Current.RouteQueryResults, _streamMergeContext.Skip.GetValueOrDefault()))
// { // {
// } // }
//} //}
}
} }
} }
return new DefaultShardingEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext); return new DefaultShardingEnumeratorAsyncStreamMergeEngine<TShardingDbContext, TEntity>(_streamMergeContext);
}
private IEnumeratorStreamMergeEngine<TEntity> DoNoOrderAppendEnumeratorStreamMergeEngine(Type shardingEntityType)
{
var isShardingDataSource = shardingEntityType.IsShardingDataSource();
var isShardingTable = shardingEntityType.IsShardingTable();
PaginationSequenceConfig dataSourceSequenceOrderConfig = null;
PaginationSequenceConfig tableSequenceOrderConfig = null;
if (isShardingDataSource)
{
var virtualDataSourceRoute = _virtualDataSource.GetRoute(shardingEntityType);
if (virtualDataSourceRoute.EnablePagination)
{
dataSourceSequenceOrderConfig = virtualDataSourceRoute.PaginationMetadata.PaginationConfigs.OrderByDescending(o => o.AppendOrder)
.FirstOrDefault(o => o.AppendIfOrderNone && typeof(TEntity).ContainPropertyName(o.PropertyName) && PaginationMatch(o));
}
}
if (isShardingTable)
{
var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntityType);
if (virtualTable.EnablePagination)
{
tableSequenceOrderConfig = virtualTable.PaginationMetadata.PaginationConfigs.OrderByDescending(o => o.AppendOrder)
.FirstOrDefault(o => o.AppendIfOrderNone && typeof(TEntity).ContainPropertyName(o.PropertyName) && PaginationMatch(o));
}
}
if (dataSourceSequenceOrderConfig != null || tableSequenceOrderConfig != null)
{
return new AppenOrderSequenceEnumeratorAsyncStreamMergeEngine<TShardingDbContext, TEntity>(_streamMergeContext, dataSourceSequenceOrderConfig, tableSequenceOrderConfig, _shardingPageManager.Current.RouteQueryResults);
}
return null;
}
private IEnumeratorStreamMergeEngine<TEntity> DoOrderSequencePaginationEnumeratorStreamMergeEngine(Type shardingEntityType)
{
var orderCount = _streamMergeContext.Orders.Count();
var primaryOrder = _streamMergeContext.Orders.First();
var isShardingDataSource = shardingEntityType.IsShardingDataSource();
var isShardingTable = shardingEntityType.IsShardingTable();
PaginationSequenceConfig dataSourceSequenceOrderConfig = null;
PaginationSequenceConfig tableSequenceOrderConfig = null;
IVirtualDataSourceRoute virtualDataSourceRoute = null;
IVirtualTable virtualTable = null;
bool dataSourceUseReverse = true;
bool tableUseReverse = true;
if (isShardingDataSource)
{
virtualDataSourceRoute = _virtualDataSource.GetRoute(shardingEntityType);
if (virtualDataSourceRoute.EnablePagination)
{
dataSourceSequenceOrderConfig = orderCount == 1 ? GetPaginationFullMatch(virtualDataSourceRoute.PaginationMetadata.PaginationConfigs, primaryOrder) : GetPaginationPrimaryMatch(virtualDataSourceRoute.PaginationMetadata.PaginationConfigs, primaryOrder);
}
}
if (isShardingTable)
{
virtualTable = _virtualTableManager.GetVirtualTable(shardingEntityType);
if (virtualTable.EnablePagination)
{
tableSequenceOrderConfig = orderCount == 1 ? GetPaginationFullMatch(virtualTable.PaginationMetadata.PaginationConfigs, primaryOrder) : GetPaginationPrimaryMatch(virtualTable.PaginationMetadata.PaginationConfigs, primaryOrder);
}
}
if (dataSourceSequenceOrderConfig != null || tableSequenceOrderConfig != null)
{
return new SequenceEnumeratorAsyncStreamMergeEngine<TShardingDbContext, TEntity>(_streamMergeContext, dataSourceSequenceOrderConfig, tableSequenceOrderConfig, _shardingPageManager.Current.RouteQueryResults, primaryOrder.IsAsc);
}
var total = _shardingPageManager.Current.RouteQueryResults.Sum(o => o.QueryResult);
if (isShardingDataSource&& virtualDataSourceRoute.EnablePagination)
{
dataSourceUseReverse =
EntityDataSourceUseReverseShardingPage(virtualDataSourceRoute, total);
}
if (isShardingTable && virtualTable.EnablePagination)
{
tableUseReverse =
EntityTableReverseShardingPage(virtualTable, total);
}
//skip过大reserve skip
if (dataSourceUseReverse && tableUseReverse)
{
return new ReverseShardingEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext, total);
}
return null;
}
private bool EntityDataSourceUseReverseShardingPage( IVirtualDataSourceRoute virtualDataSourceRoute,long total)
{
if (virtualDataSourceRoute.PaginationMetadata.EnableReverseShardingPage && _streamMergeContext.Take.GetValueOrDefault() > 0)
{
if (virtualDataSourceRoute.PaginationMetadata.IsUseReverse(_streamMergeContext.Skip.GetValueOrDefault(), total))
{
return true;
}
}
return false;
}
private bool EntityTableReverseShardingPage( IVirtualTable virtualTable, long total)
{
if (virtualTable.PaginationMetadata.EnableReverseShardingPage && _streamMergeContext.Take.GetValueOrDefault() > 0)
{
if (virtualTable.PaginationMetadata.IsUseReverse(_streamMergeContext.Skip.GetValueOrDefault(), total))
{
return true;
}
}
return false;
}
private PaginationSequenceConfig GetPaginationFullMatch(ISet<PaginationSequenceConfig> paginationSequenceConfigs, PropertyOrder primaryOrder)
{
return paginationSequenceConfigs.Where(o => !o.PaginationMatchEnum.HasFlag(PaginationMatchEnum.PrimaryMatch)).FirstOrDefault(o => PaginationPrimaryMatch(o, primaryOrder));
}
private PaginationSequenceConfig GetPaginationPrimaryMatch(ISet<PaginationSequenceConfig> paginationSequenceConfigs, PropertyOrder primaryOrder)
{
return paginationSequenceConfigs.Where(o => o.PaginationMatchEnum.HasFlag(PaginationMatchEnum.PrimaryMatch)).FirstOrDefault(o => PaginationPrimaryMatch(o, primaryOrder));
} }
private bool PaginationMatch(PaginationSequenceConfig paginationSequenceConfig) private bool PaginationMatch(PaginationSequenceConfig paginationSequenceConfig)

View File

@ -1,3 +1,4 @@
using System;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.Internal.StreamMerge.ReWrite; using ShardingCore.Core.Internal.StreamMerge.ReWrite;
using ShardingCore.Core.Internal.Visitors; using ShardingCore.Core.Internal.Visitors;
@ -39,6 +40,10 @@ namespace ShardingCore.Sharding
public GroupByContext GroupByContext { get; } public GroupByContext GroupByContext { get; }
public IEnumerable<TableRouteResult> TableRouteResults { get; } public IEnumerable<TableRouteResult> TableRouteResults { get; }
public DataSourceRouteResult DataSourceRouteResult { get; } public DataSourceRouteResult DataSourceRouteResult { get; }
/// <summary>
/// 本次查询涉及的对象
/// </summary>
public ISet<Type> QueryEntities { get; }
public StreamMergeContext(IQueryable<T> source,IShardingDbContext shardingDbContext, public StreamMergeContext(IQueryable<T> source,IShardingDbContext shardingDbContext,
DataSourceRouteResult dataSourceRouteResult, DataSourceRouteResult dataSourceRouteResult,
@ -56,6 +61,7 @@ namespace ShardingCore.Sharding
SelectContext = reWriteResult.SelectContext; SelectContext = reWriteResult.SelectContext;
GroupByContext = reWriteResult.GroupByContext; GroupByContext = reWriteResult.GroupByContext;
_reWriteSource = reWriteResult.ReWriteQueryable; _reWriteSource = reWriteResult.ReWriteQueryable;
QueryEntities = source.ParseQueryableRoute();
DataSourceRouteResult = dataSourceRouteResult; DataSourceRouteResult = dataSourceRouteResult;
TableRouteResults= tableRouteResults; TableRouteResults= tableRouteResults;
//RouteResults = _tableTableRouteRuleEngineFactory.Route(_shardingDbContext.ShardingDbContextType, _source); //RouteResults = _tableTableRouteRuleEngineFactory.Route(_shardingDbContext.ShardingDbContextType, _source);

View File

@ -2,6 +2,8 @@ using ShardingCore.Sharding.ShardingQueryExecutors;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Sharding.StreamMergeEngines namespace ShardingCore.Sharding.StreamMergeEngines
{ {
@ -11,7 +13,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines
* @Date: Saturday, 14 August 2021 22:07:28 * @Date: Saturday, 14 August 2021 22:07:28
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class AsyncEnumerableStreamMergeEngine<T> : IAsyncEnumerable<T>, IEnumerable<T> public class AsyncEnumerableStreamMergeEngine<TShardingDbContext,T> : IAsyncEnumerable<T>, IEnumerable<T>
where TShardingDbContext:DbContext,IShardingDbContext
{ {
private readonly StreamMergeContext<T> _mergeContext; private readonly StreamMergeContext<T> _mergeContext;
@ -24,7 +27,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
#if !EFCORE2 #if !EFCORE2
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
{ {
return new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync(cancellationToken) return new EnumeratorShardingQueryExecutor<TShardingDbContext,T>(_mergeContext).ExecuteAsync(cancellationToken)
.GetAsyncEnumerator(cancellationToken); .GetAsyncEnumerator(cancellationToken);
} }
#endif #endif
@ -32,7 +35,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
#if EFCORE2 #if EFCORE2
IAsyncEnumerator<T> IAsyncEnumerable<T>.GetEnumerator() IAsyncEnumerator<T> IAsyncEnumerable<T>.GetEnumerator()
{ {
return ((IAsyncEnumerable<T>)new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync()) return ((IAsyncEnumerable<T>)new EnumeratorShardingQueryExecutor<TShardingDbContext,T>(_mergeContext).ExecuteAsync())
.GetEnumerator(); .GetEnumerator();
} }
#endif #endif
@ -41,7 +44,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public IEnumerator<T> GetEnumerator() public IEnumerator<T> GetEnumerator()
{ {
return ((IEnumerable<T>)new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync()) return ((IEnumerable<T>)new EnumeratorShardingQueryExecutor<TShardingDbContext,T>(_mergeContext).ExecuteAsync())
.GetEnumerator(); .GetEnumerator();
} }

View File

@ -3,9 +3,12 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.Internal.Visitors; using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators; using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync; using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.PaginationConfigurations; using ShardingCore.Sharding.PaginationConfigurations;
@ -21,13 +24,16 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class AppenOrderSequenceEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity> public class AppenOrderSequenceEnumeratorAsyncStreamMergeEngine<TShardingDbContext,TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
where TShardingDbContext : DbContext, IShardingDbContext
{ {
private readonly PaginationSequenceConfig _appendPaginationSequenceConfig; private readonly PaginationSequenceConfig _dataSourceSequenceOrderConfig;
private readonly PaginationSequenceConfig _tableSequenceOrderConfig;
private readonly ICollection<RouteQueryResult<long>> _routeQueryResults; private readonly ICollection<RouteQueryResult<long>> _routeQueryResults;
public AppenOrderSequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PaginationSequenceConfig appendPaginationSequenceConfig, ICollection<RouteQueryResult<long>> routeQueryResults) : base(streamMergeContext) public AppenOrderSequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PaginationSequenceConfig dataSourceSequenceOrderConfig, PaginationSequenceConfig tableSequenceOrderConfig, ICollection<RouteQueryResult<long>> routeQueryResults) : base(streamMergeContext)
{ {
_appendPaginationSequenceConfig = appendPaginationSequenceConfig; _dataSourceSequenceOrderConfig = dataSourceSequenceOrderConfig;
_tableSequenceOrderConfig = tableSequenceOrderConfig;
_routeQueryResults = routeQueryResults; _routeQueryResults = routeQueryResults;
} }
@ -44,17 +50,60 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
var sortRouteResults = _routeQueryResults.Select(o => new var sortRouteResults = _routeQueryResults.Select(o => new
{ {
DataSourceName=o.DataSourceName,
Tail = o.TableRouteResult.ReplaceTables.First().Tail, Tail = o.TableRouteResult.ReplaceTables.First().Tail,
RouteQueryResult = o RouteQueryResult = o
}).OrderBy(o => o.Tail, _appendPaginationSequenceConfig.TailComparer).ToList(); });
var skipCount = skip;
//分库是主要排序
var dataSourceOrderMain = _dataSourceSequenceOrderConfig != null;
var reSetOrders = new List<PropertyOrder>();
if (dataSourceOrderMain)
{
//if sharding data source
var appendAsc = _dataSourceSequenceOrderConfig.AppendAsc;
//if sharding table
var useThenBy = dataSourceOrderMain && _tableSequenceOrderConfig != null;
if (appendAsc)
{
sortRouteResults = sortRouteResults.OrderBy(o => o.DataSourceName,
_dataSourceSequenceOrderConfig.RouteComparer)
.ThenByIf(o => o.Tail, useThenBy&& _tableSequenceOrderConfig.AppendAsc, _tableSequenceOrderConfig.RouteComparer)
.ThenByDescendingIf(o => o.Tail, useThenBy&& !_tableSequenceOrderConfig.AppendAsc, _tableSequenceOrderConfig.RouteComparer);
}
else
{
sortRouteResults = sortRouteResults.OrderByDescending(o => o.DataSourceName,
_dataSourceSequenceOrderConfig.RouteComparer).ThenByDescendingIf(o => o.Tail, useThenBy, _tableSequenceOrderConfig.RouteComparer);
}
reSetOrders.Add(new PropertyOrder(_dataSourceSequenceOrderConfig.PropertyName, _dataSourceSequenceOrderConfig.AppendAsc));
if (useThenBy)
{
reSetOrders.Add(new PropertyOrder(_tableSequenceOrderConfig.PropertyName, _tableSequenceOrderConfig.AppendAsc));
}
}
else
{
var appendAsc = _tableSequenceOrderConfig.AppendAsc;
if (appendAsc)
{
sortRouteResults = sortRouteResults.OrderBy(o => o.Tail, _tableSequenceOrderConfig.RouteComparer);
}
else
{
sortRouteResults =
sortRouteResults.OrderByDescending(o => o.Tail, _tableSequenceOrderConfig.RouteComparer);
}
reSetOrders.Add(new PropertyOrder(_tableSequenceOrderConfig.PropertyName, _tableSequenceOrderConfig.AppendAsc));
}
var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o=>o.RouteQueryResult)).Skip(skip).Take(take).ToList(); var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o=>o.RouteQueryResult)).Skip(skip).Take(take).ToList();
StreamMergeContext.ReSetOrders(new [] { new PropertyOrder(_appendPaginationSequenceConfig.PropertyName, true) }); StreamMergeContext.ReSetOrders(reSetOrders);
var enumeratorTasks = sequenceResults.Select(sequenceResult => var enumeratorTasks = sequenceResults.Select(sequenceResult =>
{ {
var newQueryable = CreateAsyncExecuteQueryable(sequenceResult.DSName,noPaginationQueryable, sequenceResult); var newQueryable = CreateAsyncExecuteQueryable(sequenceResult.DSName,noPaginationQueryable, sequenceResult, reSetOrders);
return AsyncQueryEnumerator(newQueryable,async); return AsyncQueryEnumerator(newQueryable,async);
}).ToArray(); }).ToArray();
@ -62,11 +111,11 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
return streamEnumerators; return streamEnumerators;
} }
private IQueryable<TEntity> CreateAsyncExecuteQueryable(string dsname,IQueryable<TEntity> noPaginationQueryable, SequenceResult sequenceResult) private IQueryable<TEntity> CreateAsyncExecuteQueryable(string dsname,IQueryable<TEntity> noPaginationQueryable, SequenceResult sequenceResult,IEnumerable<PropertyOrder> reSetOrders)
{ {
var shardingDbContext = StreamMergeContext.CreateDbContext(dsname,sequenceResult.TableRouteResult); var shardingDbContext = StreamMergeContext.CreateDbContext(dsname,sequenceResult.TableRouteResult);
DbContextQueryStore.TryAdd(sequenceResult.TableRouteResult, shardingDbContext); DbContextQueryStore.TryAdd(sequenceResult.TableRouteResult, shardingDbContext);
var newQueryable = (IQueryable<TEntity>)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take).OrderWithExpression(new PropertyOrder[]{new PropertyOrder(_appendPaginationSequenceConfig.PropertyName,true)})) var newQueryable = (IQueryable<TEntity>)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take).OrderWithExpression(reSetOrders))
.ReplaceDbContextQueryable(shardingDbContext); .ReplaceDbContextQueryable(shardingDbContext);
return newQueryable; return newQueryable;
} }

View File

@ -1,8 +1,10 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators; using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync; using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions; using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
@ -16,7 +18,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class DefaultShardingEnumeratorAsyncStreamMergeEngine<TEntity>:AbstractEnumeratorAsyncStreamMergeEngine<TEntity> public class DefaultShardingEnumeratorAsyncStreamMergeEngine<TShardingDbContext,TEntity> :AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
where TShardingDbContext : DbContext, IShardingDbContext
{ {
public DefaultShardingEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext) public DefaultShardingEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
{ {

View File

@ -2,10 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.Internal.Visitors; using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators; using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync; using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions; using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;

View File

@ -2,9 +2,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions; using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators; using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync; using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.PaginationConfigurations; using ShardingCore.Sharding.PaginationConfigurations;
@ -20,14 +22,17 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class SequenceEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity> public class SequenceEnumeratorAsyncStreamMergeEngine<TShardingDbContext,TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
where TShardingDbContext : DbContext, IShardingDbContext
{ {
private readonly PaginationSequenceConfig _orderPaginationSequenceConfig; private readonly PaginationSequenceConfig _dataSourceSequenceMatchOrderConfig;
private readonly PaginationSequenceConfig _tableSequenceMatchOrderConfig;
private readonly ICollection<RouteQueryResult<long>> _routeQueryResults; private readonly ICollection<RouteQueryResult<long>> _routeQueryResults;
private readonly bool _isAsc; private readonly bool _isAsc;
public SequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PaginationSequenceConfig orderPaginationSequenceConfig, ICollection<RouteQueryResult<long>> routeQueryResults, bool isAsc) : base(streamMergeContext) public SequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PaginationSequenceConfig dataSourceSequenceMatchOrderConfig, PaginationSequenceConfig tableSequenceMatchOrderConfig, ICollection<RouteQueryResult<long>> routeQueryResults, bool isAsc) : base(streamMergeContext)
{ {
_orderPaginationSequenceConfig = orderPaginationSequenceConfig; _dataSourceSequenceMatchOrderConfig = dataSourceSequenceMatchOrderConfig;
_tableSequenceMatchOrderConfig = tableSequenceMatchOrderConfig;
_routeQueryResults = routeQueryResults; _routeQueryResults = routeQueryResults;
_isAsc = isAsc; _isAsc = isAsc;
} }
@ -42,13 +47,43 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
var take = StreamMergeContext.Take; var take = StreamMergeContext.Take;
if (take.HasValue && take.Value <= 0) if (take.HasValue && take.Value <= 0)
throw new ShardingCoreException("take must gt 0"); throw new ShardingCoreException("take must gt 0");
//分库是主要排序
var dataSourceOrderMain = _dataSourceSequenceMatchOrderConfig != null;
var sortRouteResults = _routeQueryResults.Select(o => new var sortRouteResults = _routeQueryResults.Select(o => new
{ {
DataSourceName=o.DataSourceName,
Tail = o.TableRouteResult.ReplaceTables.First().Tail, Tail = o.TableRouteResult.ReplaceTables.First().Tail,
RouteQueryResult = o RouteQueryResult = o
}).OrderByIf(o => o.Tail, _isAsc, _orderPaginationSequenceConfig.TailComparer) });
.OrderByDescendingIf(o => o.Tail, !_isAsc, _orderPaginationSequenceConfig.TailComparer).ToList(); if (dataSourceOrderMain)
{
//是否有两级排序
var useThenBy = dataSourceOrderMain && _tableSequenceMatchOrderConfig != null;
if (_isAsc)
{
sortRouteResults = sortRouteResults.OrderBy(o => o.DataSourceName,
_dataSourceSequenceMatchOrderConfig.RouteComparer).ThenByIf(o=>o.Tail, useThenBy, _tableSequenceMatchOrderConfig.RouteComparer);
}
else
{
sortRouteResults = sortRouteResults.OrderByDescending(o => o.DataSourceName,
_dataSourceSequenceMatchOrderConfig.RouteComparer).ThenByDescendingIf(o => o.Tail, useThenBy, _tableSequenceMatchOrderConfig.RouteComparer);
}
}
else
{
if (_isAsc)
{
sortRouteResults =
sortRouteResults.OrderBy(o => o.Tail, _tableSequenceMatchOrderConfig.RouteComparer);
}
else
{
sortRouteResults =
sortRouteResults.OrderByDescending(o => o.Tail, _tableSequenceMatchOrderConfig.RouteComparer);
}
}
var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o => o.RouteQueryResult)).Skip(skip).Take(take).ToList(); var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o => o.RouteQueryResult)).Skip(skip).Take(take).ToList();

View File

@ -1,6 +1,8 @@
using System.Linq; using System.Linq;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators; using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions; using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
@ -12,7 +14,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
* @Date: Thursday, 02 September 2021 20:58:10 * @Date: Thursday, 02 September 2021 20:58:10
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class SingleQueryEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity> public class SingleQueryEnumeratorAsyncStreamMergeEngine<TShardingDbContext, TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
where TShardingDbContext : DbContext, IShardingDbContext
{ {
public SingleQueryEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext) public SingleQueryEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
{ {
@ -41,7 +44,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators) public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
{ {
if (streamsAsyncEnumerators.Length != 1) if (streamsAsyncEnumerators.Length != 1)
throw new ShardingCoreException($"{nameof(SingleQueryEnumeratorAsyncStreamMergeEngine<TEntity>)} has more {nameof(IStreamMergeAsyncEnumerator<TEntity>)}"); throw new ShardingCoreException($"{nameof(SingleQueryEnumeratorAsyncStreamMergeEngine<TShardingDbContext,TEntity>)} has more {nameof(IStreamMergeAsyncEnumerator<TEntity>)}");
return streamsAsyncEnumerators[0]; return streamsAsyncEnumerators[0];
} }
} }

View File

@ -77,6 +77,7 @@ namespace ShardingCore
{ {
var routeType = _shardingConfigOption.GetVirtualDataSourceRouteType(entityType); var routeType = _shardingConfigOption.GetVirtualDataSourceRouteType(entityType);
var virtualRoute = CreateVirtualDataSourceRoute(routeType); var virtualRoute = CreateVirtualDataSourceRoute(routeType);
virtualRoute.Init();
virtualDataSource.AddVirtualDataSourceRoute(virtualRoute); virtualDataSource.AddVirtualDataSourceRoute(virtualRoute);
} }
if (entityType.IsShardingTable()) if (entityType.IsShardingTable())

View File

@ -1,32 +1,45 @@
using System; using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
namespace ShardingCore.VirtualRoutes.Abstractions namespace ShardingCore.VirtualRoutes.Abstractions
{ {
/* /*
* @Author: xjm * @Author: xjm
* @Description: * @Description:sharding table route by date time
* @Date: Wednesday, 27 January 2021 12:29:19 * @Date: Wednesday, 27 January 2021 12:29:19
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public abstract class AbstractShardingTimeKeyDateTimeVirtualTableRoute<T>:AbstractShardingOperatorVirtualTableRoute<T,DateTime> where T:class,IShardingTable /// <summary>
/// time type is date time
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class AbstractShardingTimeKeyDateTimeVirtualTableRoute<T> : AbstractShardingOperatorVirtualTableRoute<T, DateTime> where T : class, IShardingTable
{ {
/// <summary>
/// how convert object to date time
/// </summary>
/// <param name="shardingKey"></param>
/// <returns></returns>
protected override DateTime ConvertToShardingKey(object shardingKey) protected override DateTime ConvertToShardingKey(object shardingKey)
{ {
return Convert.ToDateTime(shardingKey); return Convert.ToDateTime(shardingKey);
} }
/// <summary>
/// how convert sharding key to tail
/// </summary>
/// <param name="shardingKey"></param>
/// <returns></returns>
public override string ShardingKeyToTail(object shardingKey) public override string ShardingKeyToTail(object shardingKey)
{ {
var time = ConvertToShardingKey(shardingKey); var time = ConvertToShardingKey(shardingKey);
return TimeFormatToTail(time); return TimeFormatToTail(time);
} }
/// <summary>
/// how format date time to tail
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
protected abstract string TimeFormatToTail(DateTime time); protected abstract string TimeFormatToTail(DateTime time);
} }

View File

@ -1,31 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
namespace ShardingCore.VirtualRoutes.Abstractions namespace ShardingCore.VirtualRoutes.Abstractions
{ {
/* /*
* @Author: xjm * @Author: xjm
* @Description: * @Description: sharding table route by time stamp (ms)
* @Date: Wednesday, 27 January 2021 13:06:01 * @Date: Wednesday, 27 January 2021 13:06:01
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
/// <summary>
/// sharding table route by time stamp (ms)
/// </summary>
/// <typeparam name="T">entity</typeparam>
public abstract class AbstractShardingTimeKeyLongVirtualTableRoute<T> : AbstractShardingOperatorVirtualTableRoute<T, long> where T : class, IShardingTable public abstract class AbstractShardingTimeKeyLongVirtualTableRoute<T> : AbstractShardingOperatorVirtualTableRoute<T, long> where T : class, IShardingTable
{ {
/// <summary>
/// how convert object to long
/// </summary>
/// <param name="shardingKey"></param>
/// <returns></returns>
protected override long ConvertToShardingKey(object shardingKey) protected override long ConvertToShardingKey(object shardingKey)
{ {
return (long)shardingKey; return (long)shardingKey;
} }
/// <summary>
/// how convert sharding key to tail
/// </summary>
/// <param name="shardingKey"></param>
/// <returns></returns>
public override string ShardingKeyToTail(object shardingKey) public override string ShardingKeyToTail(object shardingKey)
{ {
var time = ConvertToShardingKey(shardingKey); var time = ConvertToShardingKey(shardingKey);
return TimeFormatToTail(time); return TimeFormatToTail(time);
} }
/// <summary>
/// how format long time to tail
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
protected abstract string TimeFormatToTail(long time); protected abstract string TimeFormatToTail(long time);
} }

View File

@ -1,9 +1,9 @@
using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.VirtualRoutes.Abstractions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.VirtualRoutes.Abstractions;
namespace ShardingCore.VirtualRoutes.Days namespace ShardingCore.VirtualRoutes.Days
{ {
@ -15,7 +15,15 @@ namespace ShardingCore.VirtualRoutes.Days
*/ */
public abstract class AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute<T>:AbstractShardingTimeKeyDateTimeVirtualTableRoute<T> where T:class,IShardingTable public abstract class AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute<T>:AbstractShardingTimeKeyDateTimeVirtualTableRoute<T> where T:class,IShardingTable
{ {
/// <summary>
/// begin time use fixed time eg.new DateTime(20xx,xx,xx)
/// </summary>
/// <returns></returns>
public abstract DateTime GetBeginTime(); public abstract DateTime GetBeginTime();
/// <summary>
/// return all tails in database
/// </summary>
/// <returns></returns>
public override List<string> GetAllTails() public override List<string> GetAllTails()
{ {
var beginTime = GetBeginTime(); var beginTime = GetBeginTime();
@ -24,7 +32,7 @@ namespace ShardingCore.VirtualRoutes.Days
//提前创建表 //提前创建表
var nowTimeStamp = DateTime.Now.AddDays(1).Date; var nowTimeStamp = DateTime.Now.AddDays(1).Date;
if (beginTime > nowTimeStamp) if (beginTime > nowTimeStamp)
throw new ArgumentException("起始时间不正确无法生成正确的表名"); throw new ArgumentException("begin time error");
var currentTimeStamp = beginTime; var currentTimeStamp = beginTime;
while (currentTimeStamp <= nowTimeStamp) while (currentTimeStamp <= nowTimeStamp)
{ {

View File

@ -26,7 +26,7 @@ namespace ShardingCore.VirtualRoutes.Days
//提前创建表 //提前创建表
var nowTimeStamp = DateTime.Now.AddDays(1).Date; var nowTimeStamp = DateTime.Now.AddDays(1).Date;
if (beginTime > nowTimeStamp) if (beginTime > nowTimeStamp)
throw new ArgumentException("起始时间不正确无法生成正确的表名"); throw new ArgumentException("begin time error");
var currentTimeStamp = beginTime; var currentTimeStamp = beginTime;
while (currentTimeStamp <= nowTimeStamp) while (currentTimeStamp <= nowTimeStamp)
{ {

View File

@ -4,7 +4,6 @@ using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
namespace ShardingCore.VirtualRoutes.Mods namespace ShardingCore.VirtualRoutes.Mods
@ -19,7 +18,7 @@ namespace ShardingCore.VirtualRoutes.Mods
/// 分表字段为int的取模分表 /// 分表字段为int的取模分表
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public abstract class AbstractSimpleShardingModKeyIntVirtualTableRoute<T>:AbstractShardingOperatorVirtualTableRoute<T,int> where T:class,IShardingTable public abstract class AbstractSimpleShardingModKeyIntVirtualTableRoute<T>: AbstractShardingOperatorVirtualTableRoute<T,int> where T:class,IShardingTable
{ {
protected readonly int Mod; protected readonly int Mod;
protected readonly int TailLength; protected readonly int TailLength;

View File

@ -4,7 +4,6 @@ using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Helpers; using ShardingCore.Helpers;
@ -20,7 +19,7 @@ namespace ShardingCore.VirtualRoutes.Mods
/// 分表字段为string的取模分表 /// 分表字段为string的取模分表
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public abstract class AbstractSimpleShardingModKeyStringVirtualTableRoute<T>:AbstractShardingOperatorVirtualTableRoute<T,string> where T:class,IShardingTable public abstract class AbstractSimpleShardingModKeyStringVirtualTableRoute<T>: AbstractShardingOperatorVirtualTableRoute<T,string> where T:class,IShardingTable
{ {
protected readonly int Mod; protected readonly int Mod;
protected readonly int TailLength; protected readonly int TailLength;

View File

@ -25,7 +25,7 @@ namespace ShardingCore.VirtualRoutes.Months
//提前创建表 //提前创建表
var nowTimeStamp =ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now); var nowTimeStamp =ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now);
if (beginTime > nowTimeStamp) if (beginTime > nowTimeStamp)
throw new ArgumentException("起始时间不正确无法生成正确的表名"); throw new ArgumentException("begin time error");
var currentTimeStamp = beginTime; var currentTimeStamp = beginTime;
while (currentTimeStamp <= nowTimeStamp) while (currentTimeStamp <= nowTimeStamp)
{ {

View File

@ -25,7 +25,7 @@ namespace ShardingCore.VirtualRoutes.Months
//提前创建表 //提前创建表
var nowTimeStamp =ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now); var nowTimeStamp =ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now);
if (beginTime > nowTimeStamp) if (beginTime > nowTimeStamp)
throw new ArgumentException("起始时间不正确无法生成正确的表名"); throw new ArgumentException("begin time error");
var currentTimeStamp = beginTime; var currentTimeStamp = beginTime;
while (currentTimeStamp <= nowTimeStamp) while (currentTimeStamp <= nowTimeStamp)
{ {

View File

@ -25,7 +25,7 @@ namespace ShardingCore.VirtualRoutes.Weeks
//提前创建表 //提前创建表
var nowTimeStamp = DateTime.Now.AddDays(7).Date; var nowTimeStamp = DateTime.Now.AddDays(7).Date;
if (beginTime > nowTimeStamp) if (beginTime > nowTimeStamp)
throw new ArgumentException("起始时间不正确无法生成正确的表名"); throw new ArgumentException("begin time error");
var currentTimeStamp = beginTime; var currentTimeStamp = beginTime;
while (currentTimeStamp <= nowTimeStamp) while (currentTimeStamp <= nowTimeStamp)
{ {

View File

@ -25,7 +25,7 @@ namespace ShardingCore.VirtualRoutes.Weeks
//提前创建表 //提前创建表
var nowTimeStamp = DateTime.Now.AddDays(7).Date; var nowTimeStamp = DateTime.Now.AddDays(7).Date;
if (beginTime > nowTimeStamp) if (beginTime > nowTimeStamp)
throw new ArgumentException("起始时间不正确无法生成正确的表名"); throw new ArgumentException("begin time error");
var currentTimeStamp = beginTime; var currentTimeStamp = beginTime;
while (currentTimeStamp <= nowTimeStamp) while (currentTimeStamp <= nowTimeStamp)
{ {

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Helpers;
using ShardingCore.VirtualRoutes.Abstractions; using ShardingCore.VirtualRoutes.Abstractions;
namespace ShardingCore.VirtualRoutes.Years namespace ShardingCore.VirtualRoutes.Years
@ -25,7 +24,7 @@ namespace ShardingCore.VirtualRoutes.Years
//提前创建表 //提前创建表
var nowTimeStamp = DateTime.Now.AddYears(1).Date; var nowTimeStamp = DateTime.Now.AddYears(1).Date;
if (beginTime > nowTimeStamp) if (beginTime > nowTimeStamp)
throw new ArgumentException("起始时间不正确无法生成正确的表名"); throw new ArgumentException("begin time error");
var currentTimeStamp = beginTime; var currentTimeStamp = beginTime;
while (currentTimeStamp <= nowTimeStamp) while (currentTimeStamp <= nowTimeStamp)
{ {

View File

@ -25,7 +25,7 @@ namespace ShardingCore.VirtualRoutes.Years
//提前创建表 //提前创建表
var nowTimeStamp = DateTime.Now.AddYears(1).Date; var nowTimeStamp = DateTime.Now.AddYears(1).Date;
if (beginTime > nowTimeStamp) if (beginTime > nowTimeStamp)
throw new ArgumentException("起始时间不正确无法生成正确的表名"); throw new ArgumentException("begin time error");
var currentTimeStamp = beginTime; var currentTimeStamp = beginTime;
while (currentTimeStamp <= nowTimeStamp) while (currentTimeStamp <= nowTimeStamp)
{ {

View File

@ -52,7 +52,7 @@ namespace ShardingCore.Test50
{ {
using (_shardingRouteManager.CreateScope()) using (_shardingRouteManager.CreateScope())
{ {
_shardingRouteManager.Current.Must.TryAdd(typeof(SysUserMod), new HashSet<string>() { "00" }); _shardingRouteManager.Current.MustTable.TryAdd(typeof(SysUserMod), new HashSet<string>() { "00" });
var mod00s = await _virtualDbContext.Set<SysUserMod>().ToListAsync(); var mod00s = await _virtualDbContext.Set<SysUserMod>().ToListAsync();
Assert.Equal(333, mod00s.Count); Assert.Equal(333, mod00s.Count);

View File

@ -1,19 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Test50.Domain.Entities; using ShardingCore.Test50.Domain.Entities;
using ShardingCore.VirtualRoutes;
using ShardingCore.VirtualRoutes.Mods; using ShardingCore.VirtualRoutes.Mods;
namespace ShardingCore.Test50.Shardings namespace ShardingCore.Test50.Shardings
{ {
/* /*
* @Author: xjm * @Author: xjm
* @Description: * @Description:
* @Date: Thursday, 14 January 2021 15:39:27 * @Date: Thursday, 14 January 2021 15:39:27
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute<SysUserMod> public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute<SysUserMod>
{ {
protected override bool EnableHintRoute => true; protected override bool EnableHintRoute => true;

View File

@ -48,7 +48,7 @@ namespace ShardingCore.Test50_2x
{ {
using (_shardingRouteManager.CreateScope()) using (_shardingRouteManager.CreateScope())
{ {
_shardingRouteManager.Current.Must.TryAdd(typeof(SysUserMod), new HashSet<string>() { "00" }); _shardingRouteManager.Current.MustTable.TryAdd(typeof(SysUserMod), new HashSet<string>() { "00" });
var mod00s = await _virtualDbContext.Set<SysUserMod>().ToListAsync(); var mod00s = await _virtualDbContext.Set<SysUserMod>().ToListAsync();
Assert.Equal(333, mod00s.Count); Assert.Equal(333, mod00s.Count);

View File

@ -48,7 +48,7 @@ namespace ShardingCore.Test50_3x
{ {
using (_shardingRouteManager.CreateScope()) using (_shardingRouteManager.CreateScope())
{ {
_shardingRouteManager.Current.Must.TryAdd(typeof(SysUserMod), new HashSet<string>() { "00" }); _shardingRouteManager.Current.MustTable.TryAdd(typeof(SysUserMod), new HashSet<string>() { "00" });
var mod00s = await _virtualDbContext.Set<SysUserMod>().ToListAsync(); var mod00s = await _virtualDbContext.Set<SysUserMod>().ToListAsync();
Assert.Equal(333, mod00s.Count); Assert.Equal(333, mod00s.Count);