修复内存排序下没有使用shardingcomparer的纠正

This commit is contained in:
xuejiaming 2021-11-08 20:41:25 +08:00
parent ac83780b67
commit 32e647a18d
14 changed files with 140 additions and 40 deletions

View File

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Sample.SqlServerShardingTable.Entities;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Helpers;
namespace Sample.SqlServerShardingTable.VirtualRoutes
{
public class OrderHashRangeVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute<Order,string>
{
protected override string ConvertToShardingKey(object shardingKey)
{
return shardingKey.ToString();
}
public override string ShardingKeyToTail(object shardingKey)
{
var stringHashCode = ShardingCoreHelper.GetStringHashCode("123");
var hashCode = stringHashCode % 10000;
if (hashCode >= 0 && hashCode <= 3000)
{
return "A";
}
else if (hashCode >= 3001 && hashCode <= 6000)
{
return "B";
}
else if (hashCode >= 6001 && hashCode <= 10000)
{
return "C";
}
else
throw new InvalidOperationException($"cant calc hash route hash code:[{stringHashCode}]");
}
public override List<string> GetAllTails()
{
return new List<string>()
{
"A", "B", "C"
};
}
protected override Expression<Func<string, bool>> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator)
{
//因为hash路由仅支持等于所以仅仅只需要写等于的情况
var t = ShardingKeyToTail(shardingKey);
switch (shardingOperator)
{
case ShardingOperatorEnum.Equal: return tail => tail == t;
default:
{
return tail => true;
}
}
}
}
}

View File

@ -8,7 +8,7 @@ using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.EntityMetadatas
{
/// <summary>
/// 默认分片对象数据管理者实现
/// 默认分片对象数据管理者实现
/// </summary>
/// <typeparam name="TShardingDbContext"></typeparam>
public class DefaultEntityMetadataManager<TShardingDbContext> : IEntityMetadataManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext

View File

@ -70,16 +70,16 @@ namespace ShardingCore.Extensions
}
/// <summary>
/// 切换数据源,保留原数据源中的Expression
/// 切换数据源,保留原数据源中的Expression
/// </summary>
/// <param name="source">数据源</param>
/// <param name="newSource">新数据源</param>
/// <param name="source">数据源</param>
/// <param name="dbContext">新数据源</param>
/// <returns></returns>
internal static IQueryable ReplaceDbContextQueryable(this IQueryable source, DbContext dbContext)
{
DbContextReplaceQueryableVisitor replaceQueryableVisitor = new DbContextReplaceQueryableVisitor(dbContext);
var newExpre = replaceQueryableVisitor.Visit(source.Expression);
return replaceQueryableVisitor.Source.Provider.CreateQuery(newExpre);
var newExpression = replaceQueryableVisitor.Visit(source.Expression);
return replaceQueryableVisitor.Source.Provider.CreateQuery(newExpression);
}
}
}

View File

@ -4,6 +4,8 @@ using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Internals;
namespace ShardingCore.Extensions
{
@ -45,40 +47,51 @@ namespace ShardingCore.Extensions
return Expression.Lambda(propertyAccess, parameter);
}
private static MethodCallExpression GenerateMethodCall<TEntity>(IQueryable<TEntity> source, string methodName, String fieldName)
private static MethodCallExpression GenerateMethodCall<TEntity>(IQueryable<TEntity> source, string methodName, String fieldName,IShardingComparer shardingComparer=null)
{
Type type = typeof(TEntity);
Type selectorResultType;
LambdaExpression selector = GenerateSelector<TEntity>(fieldName, out selectorResultType);
MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName,
new Type[] {type, selectorResultType},
source.Expression, Expression.Quote(selector));
MethodCallExpression resultExp;
if (shardingComparer == null)
{
resultExp = Expression.Call(typeof(Queryable), methodName,
new Type[] { type, selectorResultType },
source.Expression, Expression.Quote(selector));
}
else
{
var comparer = Activator.CreateInstance(typeof(InMemoryShardingComparer<>).GetGenericType0(selectorResultType), shardingComparer);
resultExp = Expression.Call(typeof(Queryable), methodName,
new Type[] { type, selectorResultType },
source.Expression, Expression.Quote(selector),Expression.Constant(comparer));
}
return resultExp;
}
#endregion
internal static IOrderedQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string fieldName)
internal static IOrderedQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string fieldName, IShardingComparer shardingComparer = null)
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.OrderBy), fieldName);
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.OrderBy), fieldName, shardingComparer);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
internal static IOrderedQueryable<TEntity> OrderByDescending<TEntity>(this IQueryable<TEntity> source, string fieldName)
internal static IOrderedQueryable<TEntity> OrderByDescending<TEntity>(this IQueryable<TEntity> source, string fieldName, IShardingComparer shardingComparer = null)
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.OrderByDescending), fieldName);
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.OrderByDescending), fieldName, shardingComparer);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
internal static IOrderedQueryable<TEntity> ThenBy<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName)
internal static IOrderedQueryable<TEntity> ThenBy<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName, IShardingComparer shardingComparer = null)
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.ThenBy), fieldName);
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.ThenBy), fieldName, shardingComparer);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
internal static IOrderedQueryable<TEntity> ThenByDescending<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName)
internal static IOrderedQueryable<TEntity> ThenByDescending<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName, IShardingComparer shardingComparer = null)
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.ThenByDescending), fieldName);
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.ThenByDescending), fieldName, shardingComparer);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
/// <summary>
@ -86,9 +99,10 @@ namespace ShardingCore.Extensions
/// </summary>
/// <param name="source"></param>
/// <param name="sortExpression">"child.name asc,child.age desc"</param>
/// <param name="shardingComparer"></param>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
internal static IOrderedQueryable<TEntity> OrderWithExpression<TEntity>(this IQueryable<TEntity> source, string sortExpression)
internal static IOrderedQueryable<TEntity> OrderWithExpression<TEntity>(this IQueryable<TEntity> source, string sortExpression, IShardingComparer shardingComparer = null)
{
String[] orderFields = sortExpression.Split(',');
IOrderedQueryable<TEntity> result = null;
@ -99,17 +113,17 @@ namespace ShardingCore.Extensions
Boolean sortDescending = (expressionPart.Length == 2) && (expressionPart[1].Equals("DESC", StringComparison.OrdinalIgnoreCase));
if (sortDescending)
{
result = currentFieldIndex == 0 ? source.OrderByDescending(sortField) : result.ThenByDescending(sortField);
result = currentFieldIndex == 0 ? source.OrderByDescending(sortField,shardingComparer) : result.ThenByDescending(sortField, shardingComparer);
}
else
{
result = currentFieldIndex == 0 ? source.OrderBy(sortField) : result.ThenBy(sortField);
result = currentFieldIndex == 0 ? source.OrderBy(sortField, shardingComparer) : result.ThenBy(sortField, shardingComparer);
}
}
return result;
}
internal static IOrderedQueryable<TEntity> OrderWithExpression<TEntity>(this IQueryable<TEntity> source, IEnumerable<PropertyOrder> propertyOrders)
internal static IOrderedQueryable<TEntity> OrderWithExpression<TEntity>(this IQueryable<TEntity> source, IEnumerable<PropertyOrder> propertyOrders, IShardingComparer shardingComparer = null)
{
IOrderedQueryable<TEntity> result = null;
var currentIndex = 0;
@ -118,11 +132,11 @@ namespace ShardingCore.Extensions
String sortField = propertyOrder.PropertyExpression;
if (propertyOrder.IsAsc)
{
result = currentIndex == 0 ? source.OrderBy(sortField) : result.ThenBy(sortField);
result = currentIndex == 0 ? source.OrderBy(sortField, shardingComparer) : result.ThenBy(sortField, shardingComparer);
}
else
{
result = currentIndex == 0 ? source.OrderByDescending(sortField) : result.ThenByDescending(sortField);
result = currentIndex == 0 ? source.OrderByDescending(sortField, shardingComparer) : result.ThenByDescending(sortField, shardingComparer);
}
currentIndex++;

View File

@ -13,9 +13,9 @@ namespace ShardingCore.Sharding
*/
public class CSharpLanguageShardingComparer<TShardingDbContext>:IShardingComparer<TShardingDbContext> where TShardingDbContext:DbContext,IShardingDbContext
{
public int Compare(IComparable a, IComparable b, bool asc)
public int Compare(IComparable x, IComparable y, bool asc)
{
return a.SafeCompareToWith(b, asc);
return x.SafeCompareToWith(y, asc);
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Sharding.Internals
{
public class InMemoryShardingComparer<T> : IComparer<T>
{
private readonly IShardingComparer _shardingComparer;
public InMemoryShardingComparer(IShardingComparer shardingComparer)
{
_shardingComparer = shardingComparer;
}
public int Compare(T x, T y)
{
if (x is IComparable a && y is IComparable b)
return _shardingComparer.Compare(a, b, true);
throw new NotImplementedException($"compare :[{typeof(T).FullName}] is not IComparable");
}
}
}

View File

@ -38,7 +38,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).First();
return q.OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).First();
return q.First();
}

View File

@ -41,7 +41,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).FirstOrDefault();
return q.OrderWithExpression(streamMergeContext.Orders,streamMergeContext.GetShardingComparer()).FirstOrDefault();
return q.FirstOrDefault();
}

View File

@ -39,7 +39,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).Last();
return q.OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).Last();
return q.Last();
}

View File

@ -38,7 +38,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).LastOrDefault();
return q.OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).LastOrDefault();
return q.LastOrDefault();
}

View File

@ -38,7 +38,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).Single();
return q.OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).Single();
return q.Single();
}

View File

@ -39,7 +39,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).SingleOrDefault();
return q.OrderWithExpression(streamMergeContext.Orders, streamMergeContext.GetShardingComparer()).SingleOrDefault();
return q.SingleOrDefault();
}

View File

@ -52,7 +52,7 @@ namespace ShardingCore.Core.Internal.StreamMerge.ReWrite
if (selectProperties.IsNotEmpty())
{
var sort = string.Join(",",selectProperties.Select(o=>$"{o.PropertyName} asc"));
reWriteQueryable = reWriteQueryable.OrderWithExpression(sort);
reWriteQueryable = reWriteQueryable.OrderWithExpression(sort,null);
var reWriteOrders = new List<PropertyOrder>(selectProperties.Count());
foreach (var orderProperty in selectProperties)
{

View File

@ -242,17 +242,18 @@ namespace ShardingCore.Core.Internal.Visitors
//单个
else
{
bool paramterAtLeft=false;
//条件在右边
bool conditionOnRight=false;
object value = null;
if (IsShardingKey(binaryExpression.Left)&&IsConstantOrMember(binaryExpression.Right))
{
paramterAtLeft = true;
conditionOnRight = true;
value = GetShardingKeyValue(binaryExpression.Right);
}
else if (IsConstantOrMember(binaryExpression.Left) && IsShardingKey(binaryExpression.Right))
{
paramterAtLeft = false;
conditionOnRight = false;
value = GetShardingKeyValue(binaryExpression.Left);
}
else
@ -260,10 +261,10 @@ namespace ShardingCore.Core.Internal.Visitors
var op = binaryExpression.NodeType switch
{
ExpressionType.GreaterThan => paramterAtLeft ? ShardingOperatorEnum.GreaterThan : ShardingOperatorEnum.LessThan,
ExpressionType.GreaterThanOrEqual => paramterAtLeft ? ShardingOperatorEnum.GreaterThanOrEqual : ShardingOperatorEnum.LessThanOrEqual,
ExpressionType.LessThan => paramterAtLeft ? ShardingOperatorEnum.LessThan : ShardingOperatorEnum.GreaterThan,
ExpressionType.LessThanOrEqual => paramterAtLeft ? ShardingOperatorEnum.LessThanOrEqual : ShardingOperatorEnum.GreaterThanOrEqual,
ExpressionType.GreaterThan => conditionOnRight ? ShardingOperatorEnum.GreaterThan : ShardingOperatorEnum.LessThan,
ExpressionType.GreaterThanOrEqual => conditionOnRight ? ShardingOperatorEnum.GreaterThanOrEqual : ShardingOperatorEnum.LessThanOrEqual,
ExpressionType.LessThan => conditionOnRight ? ShardingOperatorEnum.LessThan : ShardingOperatorEnum.GreaterThan,
ExpressionType.LessThanOrEqual => conditionOnRight ? ShardingOperatorEnum.LessThanOrEqual : ShardingOperatorEnum.GreaterThanOrEqual,
ExpressionType.Equal => ShardingOperatorEnum.Equal,
ExpressionType.NotEqual => ShardingOperatorEnum.NotEqual,
_ => ShardingOperatorEnum.UnKnown