优化强制路由,添加断言路由,添加提示路由

This commit is contained in:
xuejmnet 2021-08-25 20:58:19 +08:00
parent 27c97a0e51
commit c8e020f51f
16 changed files with 227 additions and 76 deletions

View File

@ -1,6 +1,6 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Sample.MySql.Domain.Maps; using Sample.MySql.Domain.Maps;
using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
namespace Sample.MySql.DbContexts namespace Sample.MySql.DbContexts

View File

@ -1,6 +1,6 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Sample.SqlServer3x.Domain.Maps; using Sample.SqlServer3x.Domain.Maps;
using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
namespace Sample.SqlServer3x namespace Sample.SqlServer3x

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using ShardingCore.Core.PhysicTables;
namespace ShardingCore.Core.QueryRouteManagers.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 25 August 2021 20:46:51
* @Email: 326308290@qq.com
*/
/// <summary>
/// 路由断言
/// </summary>
public interface IRouteAssert
{
void Assert(List<IPhysicTable> allPhysicTables, List<IPhysicTable> resultPhysicTables);
}
public interface IRouteAssert<T> : IRouteAssert where T : class, IShardingTable
{
}
}

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
@ -15,15 +16,23 @@ namespace ShardingCore.Core.QueryRouteManagers
*/ */
public class ShardingRouteContext public class ShardingRouteContext
{ {
/// <summary>
/// 强制路由直接返回对应的后缀表
/// </summary>
public Dictionary<Type, HashSet<string>> Must { get; } public Dictionary<Type, HashSet<string>> Must { get; }
public Dictionary<Type, HashSet<string>> Should { get; } /// <summary>
public Dictionary<Type, HashSet<string>> ShouldNot { get; } /// 提示路由会经过断言的强制路由
/// </summary>
public Dictionary<Type, HashSet<string>> Hint { get; }
/// <summary>
/// 断言
/// </summary>
public Dictionary<Type, LinkedList<IRouteAssert>> Assert { get; }
private ShardingRouteContext() private ShardingRouteContext()
{ {
Must = new Dictionary<Type, HashSet<string>>(); Must = new Dictionary<Type, HashSet<string>>();
Should = new Dictionary<Type, HashSet<string>>(); Hint = new Dictionary<Type, HashSet<string>>();
ShouldNot = new Dictionary<Type, HashSet<string>>(); Assert = new Dictionary<Type, LinkedList<IRouteAssert>>();
} }
public static ShardingRouteContext Create() public static ShardingRouteContext Create()

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/8/25 17:23:42
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public abstract class AbstractShardingAssertVirtualTableRoute<T, TKey> : AbstractVirtualTableRoute<T, TKey> where T : class, IShardingTable
{
}
}

View File

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/8/25 17:23:42
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public abstract class AbstractShardingFilterVirtualTableRoute<T, TKey> : AbstractVirtualTableRoute<T, TKey> where T : class, IShardingTable
{
public ShardingRouteContext CurrentShardingRouteContext =>
ShardingContainer.GetService<IShardingRouteManager>().Current;
/// <summary>
/// 启用提示路由
/// </summary>
protected virtual bool EnableHintRoute => false;
/// <summary>
/// 启用断言路由
/// </summary>
protected virtual bool EnableAssertRoute => false;
public override List<IPhysicTable> RouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable)
{
//强制路由不经过断言
if (EnableHintRoute)
{
if (CurrentShardingRouteContext != null)
{
if (CurrentShardingRouteContext.TryGetMustTail<T>(out HashSet<string> mustTails) && mustTails.IsNotEmpty())
{
var physicTables = allPhysicTables.Where(o => mustTails.Contains(o.Tail)).ToList();
if (physicTables.IsEmpty()||physicTables.Count!=mustTails.Count)
throw new ShardingCoreException(
$" sharding route must error:[{ShardingEntityType.FullName}]-->[{string.Join(",",mustTails)}]");
return physicTables;
}
if (CurrentShardingRouteContext.TryGetHintTail<T>(out HashSet<string> hintTails) && hintTails.IsNotEmpty())
{
var physicTables = allPhysicTables.Where(o => hintTails.Contains(o.Tail)).ToList();
if (physicTables.IsEmpty()||physicTables.Count!=hintTails.Count)
throw new ShardingCoreException(
$" sharding route hint error:[{ShardingEntityType.FullName}]-->[{string.Join(",",hintTails)}]");
ProcessAssertRoutes(allPhysicTables, physicTables);
return physicTables;
}
}
}
var filterPhysicTables = DoRouteWithPredicate(allPhysicTables,queryable);
//后拦截器
var resultPhysicTables = AfterPhysicTableFilter(allPhysicTables,filterPhysicTables);
//最后处理断言
ProcessAssertRoutes(allPhysicTables, resultPhysicTables);
return resultPhysicTables;
}
private void ProcessAssertRoutes(List<IPhysicTable> allPhysicTables,List<IPhysicTable> filterPhysicTables)
{
if (EnableAssertRoute)
{
if (CurrentShardingRouteContext != null && CurrentShardingRouteContext.TryGetAssertTail<T>(out ICollection<IRouteAssert> routeAsserts) && routeAsserts.IsNotEmpty())
{
foreach (var routeAssert in routeAsserts)
{
routeAssert.Assert(allPhysicTables, filterPhysicTables);
}
}
}
}
protected abstract List<IPhysicTable> DoRouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable);
/// <summary>
/// 物理表过滤后
/// </summary>
/// <param name="allPhysicTables">所有的物理表</param>
/// <param name="filterPhysicTables">过滤后的物理表</param>
/// <returns></returns>
protected virtual List<IPhysicTable> AfterPhysicTableFilter(List<IPhysicTable> allPhysicTables, List<IPhysicTable> filterPhysicTables)
{
return filterPhysicTables;
}
}
}

View File

@ -15,7 +15,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
* @Date: Saturday, 19 December 2020 19:55:24 * @Date: Saturday, 19 December 2020 19:55:24
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public abstract class AbstractShardingOperatorVirtualTableRoute<T, TKey> : AbstractVirtualTableRoute<T, TKey> where T : class, IShardingTable public abstract class AbstractShardingOperatorVirtualTableRoute<T, TKey> : AbstractShardingFilterVirtualTableRoute<T, TKey> where T : class, IShardingTable
{ {
protected override List<IPhysicTable> DoRouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable) protected override List<IPhysicTable> DoRouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable)
{ {

View File

@ -19,62 +19,17 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{ {
public Type ShardingEntityType => typeof(T); public Type ShardingEntityType => typeof(T);
public virtual ShardingRouteContext CurrentShardingRouteContext =>
ShardingContainer.GetService<IShardingRouteManager>().Current;
/// <summary>
/// 启用提示路由
/// </summary>
protected virtual bool EnableHintRoute => false;
/// <summary>
/// 跳过表达式路由
/// </summary>
protected virtual bool SkipRouteWithPredicate =>
CurrentShardingRouteContext != null && CurrentShardingRouteContext.TryGetMustTail<T>(out HashSet<string> mustTails) && mustTails.IsNotEmpty();
protected abstract TKey ConvertToShardingKey(object shardingKey); protected abstract TKey ConvertToShardingKey(object shardingKey);
public abstract string ShardingKeyToTail(object shardingKey); public abstract string ShardingKeyToTail(object shardingKey);
/// <summary> /// <summary>
/// 对外路由方法 /// 对外路由方法
/// </summary> /// </summary>
/// <param name="allPhysicTables"></param> /// <param name="allPhysicTables"></param>
/// <param name="queryable"></param> /// <param name="queryable"></param>
/// <returns></returns> /// <returns></returns>
public virtual List<IPhysicTable> RouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable) public abstract List<IPhysicTable> RouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable);
{
if (EnableHintRoute&&SkipRouteWithPredicate)
{
var tails = CurrentShardingRouteContext.Must[ShardingEntityType];
var physicTables = allPhysicTables.Where(o => tails.Contains(o.Tail)).ToList();
if (physicTables.IsEmpty())
throw new ShardingCoreException(
$" sharding route must error:[{ShardingEntityType.FullName}]-->[{string.Join(",",tails)}]");
return physicTables;
}
var filterPhysicTables = BeforePhysicTableFilter(allPhysicTables);
filterPhysicTables = DoRouteWithPredicate(filterPhysicTables, queryable);
return AfterPhysicTableFilter(allPhysicTables, filterPhysicTables);
}
protected virtual List<IPhysicTable> BeforePhysicTableFilter(List<IPhysicTable> allPhysicTables)
{
return allPhysicTables;
}
/// <summary>
/// 实际路由
/// </summary>
/// <param name="allPhysicTables"></param>
/// <param name="queryable"></param>
/// <returns></returns>
protected abstract List<IPhysicTable> DoRouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable);
/// <summary>
/// 物理表过滤后
/// </summary>
/// <param name="allPhysicTables">所有的物理表</param>
/// <param name="filterPhysicTables">过滤后的物理表</param>
/// <returns></returns>
protected virtual List<IPhysicTable> AfterPhysicTableFilter(List<IPhysicTable> allPhysicTables, List<IPhysicTable> filterPhysicTables)
{
return filterPhysicTables;
}
public abstract IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKeyValue); public abstract IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKeyValue);
/// <summary> /// <summary>

View File

@ -0,0 +1,31 @@
using System;
using System.Runtime.Serialization;
namespace ShardingCore.Exceptions
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 25 August 2021 19:20:14
* @Email: 326308290@qq.com
*/
public class ShardingCoreAssertException:ShardingCoreException
{
public ShardingCoreAssertException()
{
}
protected ShardingCoreAssertException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public ShardingCoreAssertException(string message) : base(message)
{
}
public ShardingCoreAssertException(string message, Exception innerException) : base(message, innerException)
{
}
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.QueryRouteManagers; using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
namespace ShardingCore.Extensions namespace ShardingCore.Extensions
@ -38,5 +39,51 @@ namespace ShardingCore.Extensions
tail = shardingRouteContext.Must[entityType]; tail = shardingRouteContext.Must[entityType];
return true; return true;
} }
public static bool TryGetHintTail<TEntity>(this ShardingRouteContext shardingRouteContext, out HashSet<string> tail) where TEntity : class,IShardingTable
{
return TryGetHintTail(shardingRouteContext,typeof(TEntity),out tail);
}
public static bool TryGetHintTail(this ShardingRouteContext shardingRouteContext,Type entityType, out HashSet<string> tail)
{
if (shardingRouteContext == null)
{
tail = null;
return false;
}
if (!entityType.IsShardingTable())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}");
if (!shardingRouteContext.Hint.ContainsKey(entityType))
{
tail = null;
return false;
}
tail = shardingRouteContext.Hint[entityType];
return true;
}
public static bool TryGetAssertTail<TEntity>(this ShardingRouteContext shardingRouteContext, out ICollection<IRouteAssert> tail)where TEntity : class,IShardingTable
{
return shardingRouteContext.TryGetAssertTail(typeof(TEntity), out tail);
}
public static bool TryGetAssertTail(this ShardingRouteContext shardingRouteContext,Type entityType, out ICollection<IRouteAssert> tail)
{
if (shardingRouteContext == null)
{
tail = null;
return false;
}
if (!entityType.IsShardingTable())
throw new ShardingCoreException($"sharding route entity type :{entityType.FullName} must impl {nameof(IShardingTable)}");
if (!shardingRouteContext.Assert.ContainsKey(entityType))
{
tail = null;
return false;
}
tail = shardingRouteContext.Assert[entityType];
return true;
}
} }
} }

View File

@ -1,5 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using ShardingCore.Test50.MySql.Domain.Maps; using ShardingCore.Test50.MySql.Domain.Maps;

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Test50.MySql.Domain.Entities; using ShardingCore.Test50.MySql.Domain.Entities;
namespace ShardingCore.Test50.MySql.Shardings namespace ShardingCore.Test50.MySql.Shardings

View File

@ -1,5 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using ShardingCore.Test50_2x.Domain.Maps; using ShardingCore.Test50_2x.Domain.Maps;

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Test50_2x.Domain.Entities; using ShardingCore.Test50_2x.Domain.Entities;
namespace ShardingCore.Test50_2x.Shardings namespace ShardingCore.Test50_2x.Shardings

View File

@ -1,5 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using ShardingCore.Test50_3x.Domain.Maps; using ShardingCore.Test50_3x.Domain.Maps;

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq.Expressions; using System.Linq.Expressions;
using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Test50_3x.Domain.Entities; using ShardingCore.Test50_3x.Domain.Entities;
namespace ShardingCore.Test50_3x.Shardings namespace ShardingCore.Test50_3x.Shardings