Merge branch 'smart-sharding-page' into main

This commit is contained in:
xuejiaming 2021-09-03 16:02:08 +08:00
commit f322eaa0b3
93 changed files with 2469 additions and 763 deletions

View File

@ -58,15 +58,15 @@ namespace Sample.SqlServer.Controllers
var sresultx11231 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Age == 198198).Select(o => o.Id).Contains("1981");
var sresultx1121 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Sum(o => o.Age);
var sresultx111 = _defaultTableDbContext.Set<SysUserMod>().FirstOrDefault(o => o.Id == "198");
var sresultx2 = _defaultTableDbContext.Set<SysUserMod>().Count(o => o.Age <= 10);
var sresultx = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").FirstOrDefault();
var sresultx33 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).FirstOrDefault();
var sresultxc = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).ToList();
var sresultxasdc = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").ToList();
var sresult = _defaultTableDbContext.Set<SysUserMod>().ToList();
//var sresultx11231 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Age == 198198).Select(o => o.Id).Contains("1981");
//var sresultx1121 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Sum(o => o.Age);
//var sresultx111 = _defaultTableDbContext.Set<SysUserMod>().FirstOrDefault(o => o.Id == "198");
//var sresultx2 = _defaultTableDbContext.Set<SysUserMod>().Count(o => o.Age <= 10);
//var sresultx = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").FirstOrDefault();
//var sresultx33 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).FirstOrDefault();
//var sresultxc = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).ToList();
//var sresultxasdc = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").ToList();
//var sresult = _defaultTableDbContext.Set<SysUserMod>().ToList();
var sysUserMod98 = result.FirstOrDefault(o => o.Id == "98");
_defaultTableDbContext.Attach(sysUserMod98);
@ -86,5 +86,11 @@ namespace Sample.SqlServer.Controllers
}
return Ok();
}
[HttpGet]
public async Task<IActionResult> Get1([FromQuery] int p,[FromQuery]int s)
{
var shardingPageResultAsync = await _defaultTableDbContext.Set<SysUserSalary>().OrderByDescending(o=>o.DateOfMonth).ToShardingPageAsync(p, s);
return Ok(shardingPageResultAsync);
}
}
}

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Sample.SqlServer.DbContexts;
using Sample.SqlServer.Domain.Entities;
@ -25,14 +27,17 @@ namespace Sample.SqlServer
public static void DbSeed(this IApplicationBuilder app)
{
using (var scope=app.ApplicationServices.CreateScope())
using (var scope = app.ApplicationServices.CreateScope())
{
var virtualDbContext =scope.ServiceProvider.GetService<DefaultShardingDbContext>();
var virtualDbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();
if (!virtualDbContext.Set<SysUserMod>().Any())
{
var ids = Enumerable.Range(1, 1000);
var userMods = new List<SysUserMod>();
var userSalaries = new List<SysUserSalary>();
var SysTests = new List<SysTest>();
var beginTime = new DateTime(2020, 1, 1);
var endTime = new DateTime(2021, 12, 1);
foreach (var id in ids)
{
userMods.Add(new SysUserMod()
@ -40,16 +45,38 @@ namespace Sample.SqlServer
Id = id.ToString(),
Age = id,
Name = $"name_{id}",
AgeGroup = Math.Abs(id % 10)
});
SysTests.Add(new SysTest()
{
Id = id.ToString(),
UserId = id.ToString()
});
var tempTime = beginTime;
var i = 0;
while (tempTime <= endTime)
{
var dateOfMonth = $@"{tempTime:yyyyMM}";
userSalaries.Add(new SysUserSalary()
{
Id = $@"{id}{dateOfMonth}",
UserId = id.ToString(),
DateOfMonth = int.Parse(dateOfMonth),
Salary = 700000 + id * 100 * i,
SalaryLong = 700000 + id * 100 * i,
SalaryDecimal = (700000 + id * 100 * i) / 100m,
SalaryDouble = (700000 + id * 100 * i) / 100d,
SalaryFloat = (700000 + id * 100 * i) / 100f
});
tempTime = tempTime.AddMonths(1);
i++;
}
}
virtualDbContext.AddRange(userMods);
virtualDbContext.AddRange(SysTests);
virtualDbContext.AddRange(userSalaries);
virtualDbContext.SaveChanges();
}
}

View File

@ -20,6 +20,7 @@ namespace Sample.SqlServer.DbContexts
//配置默认和DefaultTableDbContext一样
modelBuilder.ApplyConfiguration(new SysUserModMap());
modelBuilder.ApplyConfiguration(new SysTestMap());
modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
}
public override Type ShardingDbContextType => this.GetType();

View File

@ -17,6 +17,7 @@ namespace Sample.SqlServer.DbContexts
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new SysUserModMap());
modelBuilder.ApplyConfiguration(new SysTestMap());
modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
}
public IRouteTail RouteTail { get; set; }

View File

@ -27,5 +27,6 @@ namespace Sample.SqlServer.Domain.Entities
/// 用户姓名
/// </summary>
public int Age { get; set; }
public int AgeGroup { get; set; }
}
}

View File

@ -0,0 +1,42 @@
using ShardingCore.Core;
namespace Sample.SqlServer.Domain.Entities
{
/*
* @Author: xjm
* @Description:
* @Date: Monday, 01 February 2021 15:43:22
* @Email: 326308290@qq.com
*/
public class SysUserSalary:IShardingTable
{
public string Id { get; set; }
public string UserId { get; set; }
/// <summary>
/// 每月的金额
/// </summary>
[ShardingTableKey]
public int DateOfMonth { get; set; }
/// <summary>
/// 工资
/// </summary>
public int Salary { get; set; }
/// <summary>
/// 工资
/// </summary>
public long SalaryLong { get; set; }
/// <summary>
/// 工资
/// </summary>
public decimal SalaryDecimal { get; set; }
/// <summary>
/// 工资
/// </summary>
public double SalaryDouble { get; set; }
/// <summary>
/// 工资
/// </summary>
public float SalaryFloat { get; set; }
}
}

View File

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Sample.SqlServer.Domain.Entities;
namespace Sample.SqlServer.Domain.Maps
{
/*
* @Author: xjm
* @Description:
* @Date: Monday, 01 February 2021 15:42:35
* @Email: 326308290@qq.com
*/
public class SysUserSalaryMap:IEntityTypeConfiguration<SysUserSalary>
{
public void Configure(EntityTypeBuilder<SysUserSalary> builder)
{
builder.HasKey(o => o.Id);
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
builder.Property(o => o.UserId).IsRequired().HasMaxLength(128);
builder.ToTable(nameof(SysUserSalary));
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Sample.SqlServer.Domain.Entities;
using ShardingCore.Sharding.PaginationConfigurations;
namespace Sample.SqlServer.Shardings
{
public class SysUserModPaginationConfiguration : IPaginationConfiguration<SysUserMod>
{
public void Configure(PaginationBuilder<SysUserMod> builder)
{
builder.PaginationSequence(o => o.Id)
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch);
}
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq.Expressions;
using Sample.SqlServer.Domain.Entities;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Sharding.PaginationConfigurations;
using ShardingCore.VirtualRoutes;
using ShardingCore.VirtualRoutes.Mods;
@ -25,5 +26,10 @@ namespace Sample.SqlServer.Shardings
public SysUserModVirtualTableRoute() : base(2,3)
{
}
public override IPaginationConfiguration<SysUserMod> CreatePaginationConfiguration()
{
return new SysUserModPaginationConfiguration();
}
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Sample.SqlServer.Domain.Entities;
using ShardingCore.Sharding.PaginationConfigurations;
namespace Sample.SqlServer.Shardings
{
public class SysUserSalaryPaginationConfiguration:IPaginationConfiguration<SysUserSalary>
{
public void Configure(PaginationBuilder<SysUserSalary> builder)
{
//builder.PaginationSequence(o => o.Id)
// .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch);
//builder.PaginationSequence(o => o.DateOfMonth)
// .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone();
builder.ConfigReverseShardingPage();
}
}
}

View File

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Sample.SqlServer.Domain.Entities;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Sharding.PaginationConfigurations;
namespace Sample.SqlServer.Shardings
{
/*
* @Author: xjm
* @Description:
* @Date: Monday, 01 February 2021 15:54:55
* @Email: 326308290@qq.com
*/
public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute<SysUserSalary,int>
{
protected override int ConvertToShardingKey(object shardingKey)
{
return Convert.ToInt32(shardingKey);
}
public override string ShardingKeyToTail(object shardingKey)
{
var time = ConvertToShardingKey(shardingKey);
return TimeFormatToTail(time);
}
public override List<string> GetAllTails()
{
var beginTime = new DateTime(2020, 1, 1);
var endTime = new DateTime(2021, 12, 1);
var list = new List<string>(24);
var tempTime = beginTime;
while (tempTime <= endTime)
{
list.Add($"{tempTime:yyyyMM}");
tempTime = tempTime.AddMonths(1);
}
return list;
}
protected string TimeFormatToTail(int time)
{
var dateOfMonth=DateTime.ParseExact($"{time}","yyyyMM",System.Globalization.CultureInfo.InvariantCulture,System.Globalization.DateTimeStyles.AdjustToUniversal);
return $"{dateOfMonth:yyyyMM}";
}
protected override Expression<Func<string, bool>> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator)
{
var t = TimeFormatToTail(shardingKey);
switch (shardingOperator)
{
case ShardingOperatorEnum.GreaterThan:
case ShardingOperatorEnum.GreaterThanOrEqual:
return tail => String.Compare(tail, t, StringComparison.Ordinal) >= 0;
case ShardingOperatorEnum.LessThan:
return tail => String.Compare(tail, t, StringComparison.Ordinal) < 0;
case ShardingOperatorEnum.LessThanOrEqual:
return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0;
case ShardingOperatorEnum.Equal: return tail => tail == t;
default:
{
#if DEBUG
Console.WriteLine($"shardingOperator is not equal scan all table tail");
#endif
return tail => true;
}
}
}
public override IPaginationConfiguration<SysUserSalary> CreatePaginationConfiguration()
{
return new SysUserSalaryPaginationConfiguration();
}
}
}

View File

@ -38,7 +38,9 @@ namespace Sample.SqlServer
//.ReplaceService<IQueryTranslationPostprocessorFactory,SqlServer2008QueryTranslationPostprocessorFactory>()//支持sqlserver2008r2
);//使用链接字符串创建dbcontext
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
});
////不支持MARS不支持追踪的
//services.AddShardingDbContext<DefaultShardingDbContext, DefaultTableDbContext>(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx2;Integrated Security=True;")
// , op =>

View File

@ -15,6 +15,7 @@ namespace Samples.AutoByDate.SqlServer.DbContexts
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new SysUserLogByDayMap());
modelBuilder.ApplyConfiguration(new TestLogByWeekMap());
}
public override Type ShardingDbContextType => this.GetType();

View File

@ -16,6 +16,7 @@ namespace Samples.AutoByDate.SqlServer.DbContexts
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new SysUserLogByDayMap());
modelBuilder.ApplyConfiguration(new TestLogByWeekMap());
}
public IRouteTail RouteTail { get; set; }

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ShardingCore.Core;
namespace Samples.AutoByDate.SqlServer.Domain.Entities
{
public class TestLogByWeek:IShardingTable
{
public string Id { get; set; }
[ShardingTableKey]
public DateTime CreateDate { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Samples.AutoByDate.SqlServer.Domain.Entities;
namespace Samples.AutoByDate.SqlServer.Domain.Maps
{
public class TestLogByWeekMap:IEntityTypeConfiguration<TestLogByWeek>
{
public void Configure(EntityTypeBuilder<TestLogByWeek> builder)
{
builder.HasKey(o => o.Id);
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
builder.ToTable((nameof(TestLogByWeek)));
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Samples.AutoByDate.SqlServer.Domain.Entities;
using Samples.AutoByDate.SqlServer.Domain.Maps;
using ShardingCore.VirtualRoutes.Weeks;
namespace Samples.AutoByDate.SqlServer.Shardings
{
public class TestLogWeekVirtualRoute:AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute<TestLogByWeek>
{
public override DateTime GetBeginTime()
{
return new DateTime(2021, 8, 1);
}
}
}

View File

@ -43,6 +43,7 @@ namespace Samples.AutoByDate.SqlServer
op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection),
(conStr,builder) => builder.UseSqlServer(conStr));
op.AddShardingTableRoute<SysUserLogByDayVirtualTableRoute>();
op.AddShardingTableRoute<TestLogWeekVirtualRoute>();
});
services.AddChronusJob();
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ShardingCore.Core.ShardingPage.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 13:46:13
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public interface IShardingPageAccessor
{
ShardingPageContext ShardingPageContext { get; set; }
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ShardingCore.Core.ShardingPage.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 13:46:37
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public interface IShardingPageManager
{
ShardingPageContext Current { get; }
/// <summary>
/// 创建分页scope
/// </summary>
/// <returns></returns>
ShardingPageScope CreateScope();
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using ShardingCore.Core.ShardingPage.Abstractions;
namespace ShardingCore.Core.ShardingPage
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 13:47:35
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ShardingPageAccessor:IShardingPageAccessor
{
private static AsyncLocal<ShardingPageContext> _shardingPageContext = new AsyncLocal<ShardingPageContext>();
/// <inheritdoc />
public ShardingPageContext ShardingPageContext
{
get => _shardingPageContext.Value;
set => _shardingPageContext.Value = value;
}
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Text;
using ShardingCore.Sharding.StreamMergeEngines;
namespace ShardingCore.Core.ShardingPage
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 13:46:55
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ShardingPageContext
{
public ICollection<RouteQueryResult<long>> RouteQueryResults { get; }
private ShardingPageContext()
{
RouteQueryResults = new LinkedList<RouteQueryResult<long>>();
}
public static ShardingPageContext Create()
{
return new ShardingPageContext();
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Text;
using ShardingCore.Core.ShardingPage.Abstractions;
namespace ShardingCore.Core.ShardingPage
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 13:50:13
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ShardingPageManager: IShardingPageManager
{
private readonly IShardingPageAccessor _shardingPageAccessor;
public ShardingPageManager(IShardingPageAccessor shardingPageAccessor)
{
_shardingPageAccessor = shardingPageAccessor;
}
public ShardingPageContext Current => _shardingPageAccessor.ShardingPageContext;
public ShardingPageScope CreateScope()
{
var shardingPageScope = new ShardingPageScope(_shardingPageAccessor);
_shardingPageAccessor.ShardingPageContext = ShardingPageContext.Create();
return shardingPageScope;
}
}
}

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Text;
using ShardingCore.Core.ShardingPage.Abstractions;
namespace ShardingCore.Core.ShardingPage
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 13:49:12
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ShardingPageScope : IDisposable
{
/// <summary>
/// 分表配置访问器
/// </summary>
public IShardingPageAccessor ShardingPageAccessor { get; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="shardingPageAccessor"></param>
public ShardingPageScope(IShardingPageAccessor shardingPageAccessor)
{
ShardingPageAccessor = shardingPageAccessor;
}
/// <summary>
/// 回收
/// </summary>
public void Dispose()
{
ShardingPageAccessor.ShardingPageContext = null;
}
}
}

View File

@ -6,6 +6,7 @@ using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.PaginationConfigurations;
namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
@ -17,6 +18,11 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
*/
public abstract class AbstractVirtualTableRoute<T, TKey> : IVirtualTableRoute<T> where T : class, IShardingTable
{
public virtual IPaginationConfiguration<T> CreatePaginationConfiguration()
{
return null;
}
public Type ShardingEntityType => typeof(T);
/// <summary>
/// 如何将分表字段转成对应的类型

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Sharding.PaginationConfigurations;
namespace ShardingCore.Core.VirtualRoutes.TableRoutes
{
@ -44,5 +45,10 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes
public interface IVirtualTableRoute<T> : IVirtualTableRoute where T : class, IShardingTable
{
/// <summary>
/// 返回null就是表示不开启分页配置
/// </summary>
/// <returns></returns>
IPaginationConfiguration<T> CreatePaginationConfiguration();
}
}

View File

@ -22,6 +22,23 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
}
public ISet<IPhysicTable> ReplaceTables { get; }
protected bool Equals(RouteResult other)
{
return Equals(ReplaceTables, other.ReplaceTables);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((RouteResult) obj);
}
public override int GetHashCode()
{
return (ReplaceTables != null ? ReplaceTables.GetHashCode() : 0);
}
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Sharding.PaginationConfigurations;
namespace ShardingCore.Core.VirtualTables
{
@ -22,6 +23,14 @@ namespace ShardingCore.Core.VirtualTables
/// 分表配置
/// </summary>
ShardingTableConfig ShardingConfig { get; }
/// <summary>
/// 分页配置
/// </summary>
PaginationMetadata PaginationMetadata { get; }
/// <summary>
/// 是否启用分页配置
/// </summary>
bool EnablePagination => PaginationMetadata != null;
/// <summary>
/// 获取所有的物理表

View File

@ -8,6 +8,7 @@ using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.PaginationConfigurations;
using ShardingCore.Utils;
namespace ShardingCore.Core.VirtualTables
@ -28,12 +29,22 @@ namespace ShardingCore.Core.VirtualTables
public Type EntityType => typeof(T);
public ShardingTableConfig ShardingConfig { get; }
public PaginationMetadata PaginationMetadata { get; }
private readonly List<IPhysicTable> _physicTables = new List<IPhysicTable>();
public OneDbVirtualTable(IVirtualTableRoute<T> virtualTableRoute)
{
_virtualTableRoute = virtualTableRoute;
ShardingConfig = ShardingKeyUtil.Parse(EntityType);
var paginationConfiguration = virtualTableRoute.CreatePaginationConfiguration();
if (paginationConfiguration != null)
{
PaginationMetadata = new PaginationMetadata();
var paginationBuilder = new PaginationBuilder<T>(PaginationMetadata);
paginationConfiguration.Configure(paginationBuilder);
}
}
public List<IPhysicTable> GetAllPhysicTables()

View File

@ -16,8 +16,11 @@ using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.ShardingAccessors.Abstractions;
using ShardingCore.Core.ShardingPage;
using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
using ShardingCore.Sharding.ShardingQueryExecutors;
namespace ShardingCore
{
@ -86,8 +89,15 @@ namespace ShardingCore
services.AddSingleton<IShardingAccessor, ShardingAccessor>();
services.AddSingleton<IShardingScopeFactory, ShardingScopeFactory>();
services.AddSingleton<IRouteTailFactory, RouteTailFactory>();
services.AddSingleton<IShardingQueryExecutor, DefaultShardingQueryExecutor>();
//route manage
services.AddSingleton<IShardingRouteManager, ShardingRouteManager>();
services.AddSingleton<IShardingRouteAccessor, ShardingRouteAccessor>();
//sharding page
services.AddSingleton<IShardingPageManager, ShardingPageManager>();
services.AddSingleton<IShardingPageAccessor, ShardingPageAccessor>();
return services;
}

View File

@ -1,12 +1,8 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.DbContexts.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.DbContexts.ShardingDbContexts;
namespace ShardingCore
{

View File

@ -13,6 +13,7 @@ using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Internal;
#if EFCORE2
using Microsoft.EntityFrameworkCore.Internal;
@ -29,178 +30,25 @@ namespace ShardingCore.EFCores
public class ShardingQueryCompiler : IQueryCompiler
{
private readonly ICurrentDbContext _currentContext;
private readonly IStreamMergeContextFactory _streamMergeContextFactory;
private readonly IShardingQueryExecutor _shardingQueryExecutor;
public ShardingQueryCompiler(ICurrentDbContext currentContext)
{
_currentContext = currentContext;
_streamMergeContextFactory = ShardingContainer.GetService<IStreamMergeContextFactory>();
_shardingQueryExecutor = ShardingContainer.GetService<IShardingQueryExecutor>();
}
private ICurrentDbContext GetCurrentDbContext()
{
return _currentContext;
}
private TResult EnumerableExecute<TResult>(IShardingDbContext shardingDbContext, Expression query, bool async)
{
Type queryEntityType;
if (async)
queryEntityType = typeof(TResult).GetGenericArguments()[0];
else
{
queryEntityType = query.Type.GetSequenceType();
}
Type type = typeof(EnumerableQuery<>);
type = type.MakeGenericType(queryEntityType);
var queryable = Activator.CreateInstance(type, query);
var streamMergeContextMethod = _streamMergeContextFactory.GetType().GetMethod("Create");
if (streamMergeContextMethod == null)
throw new ShardingCoreException("cant found IStreamMergeContextFactory method [Create]");
var streamMergeContext = streamMergeContextMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(_streamMergeContextFactory, new[] { queryable, shardingDbContext });
Type streamMergeEngineType = typeof(AsyncEnumerableStreamMergeEngine<>);
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
return (TResult)Activator.CreateInstance(streamMergeEngineType, streamMergeContext);
}
public TResult Execute<TResult>(Expression query)
{
var async = false;
var currentDbContext = GetCurrentDbContext().Context;
if (currentDbContext is IShardingDbContext shardingDbContext)
{
//如果根表达式为iqueryable表示需要迭代
if (query.Type.HasImplementedRawGeneric(typeof(IQueryable<>)))
{
return EnumerableExecute<TResult>(shardingDbContext, query, async);
}
if (query is MethodCallExpression methodCallExpression)
{
switch (methodCallExpression.Method.Name)
{
case nameof(Enumerable.First):
return GenericMergeExecute<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.FirstOrDefault):
return GenericMergeExecute<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Last):
return GenericMergeExecute<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.LastOrDefault):
return GenericMergeExecute<TResult>(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Single):
return GenericMergeExecute<TResult>(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.SingleOrDefault):
return GenericMergeExecute<TResult>(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Count):
return EnsureMergeExecute<TResult>(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.LongCount):
return EnsureMergeExecute<TResult>(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Any):
return EnsureMergeExecute<TResult>(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.All):
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Max):
return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Min):
return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Sum):
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Average):
return EnsureMergeExecute2<TResult>(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Contains):
return EnsureMergeExecute<TResult>(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
}
}
#if !EFCORE2
throw new ShardingCoreException($"db context operator not support query expression:[{query.Print()}] result type:[{typeof(TResult).FullName}]");
#endif
#if EFCORE2
throw new ShardingCoreException($"db context operator not support query expression:[{query}] result type:[{typeof(TResult).FullName}]");
#endif
//IQueryable<TResult> queryable = new EnumerableQuery<TResult>(expression);
//var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext);
//var streamMergeEngine = AsyncEnumerableStreamMergeEngine<TResult>.Create<TResult>(streamMergeContext);
//return streamMergeEngine.GetAsyncEnumerator();
}
throw new ShardingCoreException("db context operator is not IShardingDbContext");
return _shardingQueryExecutor.Execute<TResult>(_currentContext, query);
}
#if !EFCORE2
public TResult ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
{
var currentDbContext = GetCurrentDbContext().Context;
var async = true;
if (currentDbContext is IShardingDbContext shardingDbContext)
{
if (typeof(TResult).HasImplementedRawGeneric(typeof(IAsyncEnumerable<>)))
{
return EnumerableExecute<TResult>(shardingDbContext, query, async);
}
if (typeof(TResult).HasImplementedRawGeneric(typeof(Task<>)))
{
if (query is MethodCallExpression methodCallExpression)
{
switch (methodCallExpression.Method.Name)
{
case nameof(Enumerable.First):
return GenericMergeExecute<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.FirstOrDefault):
return GenericMergeExecute<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Last):
return GenericMergeExecute<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.LastOrDefault):
return GenericMergeExecute<TResult>(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Single):
return GenericMergeExecute<TResult>(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.SingleOrDefault):
return GenericMergeExecute<TResult>(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Count):
return EnsureMergeExecute<TResult>(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.LongCount):
return EnsureMergeExecute<TResult>(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Any):
return EnsureMergeExecute<TResult>(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.All):
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Max):
return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Min):
return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Sum):
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Average):
return EnsureMergeExecute2<TResult>(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Contains):
return EnsureMergeExecute<TResult>(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
}
}
}
throw new ShardingCoreException($"db context operator not support query expression:[{query.Print()}] result type:[{typeof(TResult).FullName}]");
//IQueryable<TResult> queryable = new EnumerableQuery<TResult>(expression);
//var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext);
//var streamMergeEngine = AsyncEnumerableStreamMergeEngine<TResult>.Create<TResult>(streamMergeContext);
//return streamMergeEngine.GetAsyncEnumerator();
}
throw new ShardingCoreException("db context operator is not IShardingDbContext");
return _shardingQueryExecutor.ExecuteAsync<TResult>(_currentContext, query, cancellationToken);
}
public Func<QueryContext, TResult> CreateCompiledQuery<TResult>(Expression query)
@ -220,58 +68,6 @@ namespace ShardingCore.EFCores
#endif
private TResult GenericMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultEntityType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamEngine, @params);
}
private TResult GenericMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType,resultType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
//typeof(TResult)==?resultType
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params);
}
private TResult EnsureMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType());
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IEnsureMergeResult<object>.MergeResultAsync) : nameof(IEnsureMergeResult<object>.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (TResult)streamEngineMethod.Invoke(streamEngine, @params);
}
private TResult EnsureMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
if (async)
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType(), typeof(TResult).GetGenericArguments()[0]);
else
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType(), typeof(TResult));
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IEnsureMergeResult<object>.MergeResultAsync) : nameof(IEnsureMergeResult<object>.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (TResult)streamEngineMethod.Invoke(streamEngine, @params);
}
#if EFCORE2
private IAsyncEnumerable<TResult> AsyncEnumerableExecute<TResult>(IShardingDbContext shardingDbContext, Expression query)
@ -369,78 +165,12 @@ namespace ShardingCore.EFCores
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression query)
{
var currentDbContext = GetCurrentDbContext().Context;
if (currentDbContext is IShardingDbContext shardingDbContext)
{
return AsyncEnumerableExecute<TResult>(shardingDbContext, query);
}
throw new ShardingCoreException("db context operator is not IShardingDbContext");
return _shardingQueryExecutor.ExecuteAsync<IAsyncEnumerable<TResult>>(_currentContext, query, cancellationToken);
}
public Task<TResult> ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
{
var currentDbContext = GetCurrentDbContext().Context;
var async = true;
if (currentDbContext is IShardingDbContext shardingDbContext)
{
if (typeof(TResult).HasImplementedRawGeneric(typeof(IAsyncEnumerable<>)))
{
return EnumerableExecuteAsync<TResult>(shardingDbContext, query, async);
}
if (query is MethodCallExpression methodCallExpression)
{
switch (methodCallExpression.Method.Name)
{
case nameof(Enumerable.First):
return GenericMergeExecuteAsync<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.FirstOrDefault):
return GenericMergeExecuteAsync<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Last):
return GenericMergeExecuteAsync<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.LastOrDefault):
return GenericMergeExecuteAsync<TResult>(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Single):
return GenericMergeExecuteAsync<TResult>(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.SingleOrDefault):
return GenericMergeExecuteAsync<TResult>(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Count):
return EnsureMergeExecuteAsync<TResult>(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.LongCount):
return EnsureMergeExecuteAsync<TResult>(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Any):
return EnsureMergeExecuteAsync<TResult>(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.All):
return EnsureMergeExecuteAsync<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Max):
return GenericMergeExecuteAsync2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Min):
return GenericMergeExecuteAsync2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Sum):
return EnsureMergeExecuteAsync2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, cancellationToken);
case nameof(Enumerable.Average):
return EnsureMergeExecuteAsync2<TResult>(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression,cancellationToken);
case nameof(Enumerable.Contains):
return EnsureMergeExecuteAsync<TResult>(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
}
}
throw new ShardingCoreException($"db context operator not support query expression:[{query}] result type:[{typeof(TResult).FullName}]");
//IQueryable<TResult> queryable = new EnumerableQuery<TResult>(expression);
//var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext);
//var streamMergeEngine = AsyncEnumerableStreamMergeEngine<TResult>.Create<TResult>(streamMergeContext);
//return streamMergeEngine.GetAsyncEnumerator();
}
throw new ShardingCoreException("db context operator is not IShardingDbContext");
return _shardingQueryExecutor.ExecuteAsync<Task<TResult>>(_currentContext, query, cancellationToken);
}
public Func<QueryContext, TResult> CreateCompiledQuery<TResult>(Expression query)

View File

@ -1,6 +1,7 @@
using System.Linq;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Sharding.Visitors;
namespace ShardingCore.Extensions
{
@ -29,7 +30,8 @@ namespace ShardingCore.Extensions
/// <returns></returns>
internal static IQueryable<T> RemoveSkip<T>(this IQueryable<T> source)
{
return (IQueryable<T>)source.Provider.CreateQuery(new RemoveSkipVisitor().Visit(source.Expression));
var expression = new RemoveSkipVisitor().Visit(source.Expression);
return (IQueryable<T>)source.Provider.CreateQuery(expression);
}
/// <summary>
@ -43,6 +45,17 @@ namespace ShardingCore.Extensions
var expression = new RemoveTakeVisitor().Visit(source.Expression);
return (IQueryable<T>) source.Provider.CreateQuery(expression);
}
internal static IQueryable<T> RemoveOrderBy<T>(this IQueryable<T> source)
{
var expression = new RemoveOrderByVisitor().Visit(source.Expression);
return (IQueryable<T>) source.Provider.CreateQuery(expression);
}
internal static IQueryable<T> RemoveOrderByDescending<T>(this IQueryable<T> source)
{
var expression = new RemoveOrderByDescendingVisitor().Visit(source.Expression);
return (IQueryable<T>) source.Provider.CreateQuery(expression);
}
/// <summary>
/// 切换数据源,保留原数据源中的Expression

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace ShardingCore.Extensions.InternalExtensions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 10:13:07
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
internal static class InternalLinqExtension
{
public static IEnumerable<TShource> OrderByIf<TShource, TKey>(this IEnumerable<TShource> source, Func<TShource, TKey> keySelector, bool condition,
IComparer<TKey>? comparer)
{
return condition ? source.OrderBy(keySelector, comparer) : source;
}
public static IEnumerable<TShource> OrderByDescendingIf<TShource, TKey>(this IEnumerable<TShource> source, Func<TShource, TKey> keySelector, bool condition,
IComparer<TKey>? comparer)
{
return condition ? source.OrderByDescending(keySelector, comparer) : source;
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using ShardingCore.Sharding.PaginationConfigurations;
namespace ShardingCore.Extensions.InternalExtensions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 13:21:09
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
internal static class InternalPaginationMetadataExtension
{
internal static bool IsUseReverse(this PaginationMetadata paginationMetadata,int skip,long total)
{
if (total < paginationMetadata.ReverseTotalGe)
return false;
return paginationMetadata.ReverseFactor * total < skip;
}
}
}

View File

@ -61,6 +61,29 @@ namespace ShardingCore.Extensions
func(item);
}
}
/// <summary>
/// 是否有差异
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static bool HasDifference<T>(this IEnumerable<T> source)
{
return source.Distinct().Count() > 1;
}
/// <summary>
/// 是否有差异
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="source"></param>
/// <param name="keySelector"></param>
/// <returns></returns>
public static bool HasDifference<T,TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector)
{
return source.Select(keySelector).Distinct().Count() > 1;
}
}
}

View File

@ -72,6 +72,17 @@ namespace ShardingCore.Extensions
return null;
}
}
/// <summary>
/// 类型X是否包含某个属性
/// </summary>
/// <param name="type"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
public static bool ContainPropertyName(this Type type, string propertyName)
{
var property = type.GetProperty(propertyName, _bindingFlags);
return property != null;
}
}
}

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.Abstractions;
@ -44,7 +46,17 @@ namespace ShardingCore.Extensions
public static string FormatRouteTail2ModelCacheKey(this string originalTail)
{
return $"{ShardingTableDbContextFormat}{originalTail}";
;
}
public static string ShardingPrint(this Expression expression)
{
#if !EFCORE2
return expression.Print();
#endif
#if EFCORE2
return expression.ToString();
#endif
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingPage.Abstractions;
namespace ShardingCore.Extensions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 10:36:51
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public static class ShardingQueryableExtension
{
public static async Task<ShardingPagedResult<T>> ToShardingPageAsync<T>(this IQueryable<T> source, int pageIndex, int pageSize)
{
//设置每次获取多少页
var take = pageSize <= 0 ? 1 : pageSize;
//设置当前页码最小1
var index = pageIndex <= 0 ? 1 : pageIndex;
//需要跳过多少页
var skip = (index - 1) * take;
var shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
using (shardingPageManager.CreateScope())
{
//获取每次总记录数
var count = await source.LongCountAsync();
if (count <= skip)
return new ShardingPagedResult<T>(new List<T>(0), count);
var data = await source.Skip(skip).Take(take).ToListAsync();
return new ShardingPagedResult<T>(data, count);
}
}
public static ShardingPagedResult<T> ToShardingPage<T>(this IQueryable<T> source, int pageIndex, int pageSize)
{
//设置每次获取多少页
var take = pageSize <= 0 ? 1 : pageSize;
//设置当前页码最小1
var index = pageIndex <= 0 ? 1 : pageIndex;
//需要跳过多少页
var skip = (index - 1) * take;
var shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
using (shardingPageManager.CreateScope())
{
//获取每次总记录数
var count = source.Count();
if (count <= skip)
return new ShardingPagedResult<T>(new List<T>(0), count);
var data = source.Skip(skip).Take(take).ToList();
return new ShardingPagedResult<T>(data, count);
}
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using System.Linq;
using ShardingCore.Sharding;
namespace ShardingCore.Extensions
{
/*
* @Author: xjm
* @Description:
* @Date: Thursday, 02 September 2021 20:46:24
* @Email: 326308290@qq.com
*/
public static class StreamMergeContextExtension
{
/// <summary>
/// 本次查询是否涉及到分表
/// </summary>
/// <param name="streamMergeContext"></param>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public static bool IsShardingQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
{
return streamMergeContext.RouteResults.Count() > 1;
}
public static bool IsSingleShardingTableQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
{
return streamMergeContext.RouteResults.First().ReplaceTables.Count(o => o.EntityType.IsShardingTable()) == 1;
}
}
}

View File

@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ShardingCore.Extensions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/1 10:22:00
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
internal static class TaskExtension
{
/// <summary>
/// 是否成功
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public static bool IsCompletedSuccessfully(this Task task)
{
return task.IsCompleted && !(task.IsCanceled || task.IsFaulted);
}
/// <summary>
/// Waits for the task to complete, unwrapping any exceptions.
/// </summary>
/// <param name="task">The task. May not be <c>null</c>.</param>
public static void WaitAndUnwrapException(this Task task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
task.GetAwaiter().GetResult();
}
/// <summary>
/// Waits for the task to complete, unwrapping any exceptions.
/// </summary>
/// <param name="task">The task. May not be <c>null</c>.</param>
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
/// <exception cref="OperationCanceledException">The <paramref name="cancellationToken"/> was cancelled before the <paramref name="task"/> completed, or the <paramref name="task"/> raised an <see cref="OperationCanceledException"/>.</exception>
public static void WaitAndUnwrapException(this Task task, CancellationToken cancellationToken)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
try
{
task.Wait(cancellationToken);
}
catch (AggregateException ex)
{
ExceptionDispatchInfo.Capture(ex).Throw();
throw ex;
}
}
/// <summary>
/// Waits for the task to complete, unwrapping any exceptions.
/// </summary>
/// <typeparam name="TResult">The type of the result of the task.</typeparam>
/// <param name="task">The task. May not be <c>null</c>.</param>
/// <returns>The result of the task.</returns>
public static TResult WaitAndUnwrapException<TResult>(this Task<TResult> task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
return task.GetAwaiter().GetResult();
}
/// <summary>
/// Waits for the task to complete, unwrapping any exceptions.
/// </summary>
/// <typeparam name="TResult">The type of the result of the task.</typeparam>
/// <param name="task">The task. May not be <c>null</c>.</param>
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
/// <returns>The result of the task.</returns>
/// <exception cref="OperationCanceledException">The <paramref name="cancellationToken"/> was cancelled before the <paramref name="task"/> completed, or the <paramref name="task"/> raised an <see cref="OperationCanceledException"/>.</exception>
public static TResult WaitAndUnwrapException<TResult>(this Task<TResult> task, CancellationToken cancellationToken)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
try
{
task.Wait(cancellationToken);
return task.Result;
}
catch (AggregateException ex)
{
ExceptionDispatchInfo.Capture(ex).Throw();
throw ex;
}
}
/// <summary>
/// Waits for the task to complete, but does not raise task exceptions. The task exception (if any) is unobserved.
/// </summary>
/// <param name="task">The task. May not be <c>null</c>.</param>
public static void WaitWithoutException(this Task task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
try
{
task.Wait();
}
catch (AggregateException)
{
}
}
/// <summary>
/// Waits for the task to complete, but does not raise task exceptions. The task exception (if any) is unobserved.
/// </summary>
/// <param name="task">The task. May not be <c>null</c>.</param>
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
/// <exception cref="OperationCanceledException">The <paramref name="cancellationToken"/> was cancelled before the <paramref name="task"/> completed.</exception>
public static void WaitWithoutException(this Task task, CancellationToken cancellationToken)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
try
{
task.Wait(cancellationToken);
}
catch (AggregateException)
{
cancellationToken.ThrowIfCancellationRequested();
}
}
}
}

View File

@ -0,0 +1,34 @@
using System.Linq.Expressions;
using System.Threading;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Sharding.Enumerators;
namespace ShardingCore.Sharding.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 27 August 2021 22:49:22
* @Email: 326308290@qq.com
*/
public interface IShardingQueryExecutor
{
/// <summary>
/// ͬ<><CDAC>ִ<EFBFBD>л<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="currentContext"></param>
/// <param name="query"></param>
/// <returns></returns>
TResult Execute<TResult>(ICurrentDbContext currentContext, Expression query);
/// <summary>
/// <20>첽ִ<ECB2BD>л<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="currentContext"></param>
/// <param name="query"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
TResult ExecuteAsync<TResult>(ICurrentDbContext currentContext, Expression query, CancellationToken cancellationToken = new CancellationToken());
}
}

View File

@ -1,4 +1,5 @@
using System.Linq;
using System.Linq.Expressions;
namespace ShardingCore.Sharding.Abstractions
{
@ -10,6 +11,6 @@ namespace ShardingCore.Sharding.Abstractions
*/
public interface IStreamMergeContextFactory
{
StreamMergeContext<T> Create<T>(IQueryable<T> queryable,IShardingDbContext shardingDbContext);
StreamMergeContext<T> Create<T>(IQueryable<T> queryable, IShardingDbContext shardingDbContext);
}
}

View File

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 15:30:32
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class InMemoryReverseStreamMergeAsyncEnumerator<T>:IStreamMergeAsyncEnumerator<T>
{
private readonly IStreamMergeAsyncEnumerator<T> _inMemoryStreamMergeAsyncEnumerator;
private bool _first = true;
private IEnumerator<T> _reverseEnumerator = Enumerable.Empty<T>().GetEnumerator();
public InMemoryReverseStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<T> inMemoryStreamMergeAsyncEnumerator)
{
_inMemoryStreamMergeAsyncEnumerator = inMemoryStreamMergeAsyncEnumerator;
}
public async ValueTask DisposeAsync()
{
await _inMemoryStreamMergeAsyncEnumerator.DisposeAsync();
_reverseEnumerator.Dispose();
}
public async ValueTask<bool> MoveNextAsync()
{
if (_first)
{
ICollection<T> _reverseCollection = new LinkedList<T>();
while(await _inMemoryStreamMergeAsyncEnumerator.MoveNextAsync())
{
_reverseCollection.Add(_inMemoryStreamMergeAsyncEnumerator.Current);
}
_reverseEnumerator = _reverseCollection.Reverse().GetEnumerator();
_first = false;
}
return _reverseEnumerator.MoveNext();
}
public T Current => _reverseEnumerator.Current;
public bool SkipFirst()
{
throw new NotImplementedException();
}
public bool HasElement()
{
throw new NotImplementedException();
}
public T ReallyCurrent => Current;
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
using ShardingCore.Core;
namespace ShardingCore.Sharding.PaginationConfigurations
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/1 17:32:36
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public interface IPaginationConfiguration<TEntity> where TEntity : class,IShardingTable
{
void Configure(PaginationBuilder<TEntity> builder);
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Core;
namespace ShardingCore.Sharding.PaginationConfigurations
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/1 17:33:12
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class PaginationBuilder<TEntity> where TEntity:class,IShardingTable
{
private readonly PaginationMetadata _metadata;
public PaginationBuilder(PaginationMetadata metadata)
{
_metadata = metadata;
}
/// <summary>
/// 分页顺序
/// </summary>
/// <param name="orderPropertyExpression"></param>
/// <typeparam name="TProperty"></typeparam>
public PaginationOrderPropertyBuilder PaginationSequence<TProperty>(Expression<Func<TEntity, TProperty>> orderPropertyExpression)
{
return new PaginationOrderPropertyBuilder(orderPropertyExpression, _metadata);
}
/// <summary>
/// 配置反向排序 仅支持单排序 当skip>= reverseTotalGe*reverseFactor使用反向排序
/// </summary>
/// <param name="reverseFactor"></param>
/// <param name="reverseTotalGe"></param>
/// <returns></returns>
public PaginationBuilder<TEntity> ConfigReverseShardingPage(double reverseFactor=0.5,long reverseTotalGe=10000L)
{
_metadata.ReverseFactor = reverseFactor;
_metadata.ReverseTotalGe = reverseTotalGe;
return this;
}
/// <summary>
/// 配置当分表数目小于多少后直接取到内存不在流式处理
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
public PaginationBuilder<TEntity> ConfigTakeInMemoryCountIfLe(int count)
{
_metadata.TakeInMemoryCountIfLe = count;
return this;
}
}
}

View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
namespace ShardingCore.Sharding.PaginationConfigurations
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 7:45:55
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class PaginationConfig
{
public PaginationConfig(LambdaExpression orderPropertyExpression, PaginationMatchEnum paginationMatchEnum= PaginationMatchEnum.Owner, IComparer<string> tailComparer=null)
{
OrderPropertyExpression = orderPropertyExpression;
OrderPropertyInfo = orderPropertyExpression.GetPropertyAccess();
PropertyName = OrderPropertyInfo.Name;
PaginationMatchEnum = paginationMatchEnum;
TailComparer = tailComparer ?? Comparer<string>.Default;
}
public LambdaExpression OrderPropertyExpression { get; set; }
public IComparer<string> TailComparer { get; set; }
public PaginationMatchEnum PaginationMatchEnum { get; set; }
public PropertyInfo OrderPropertyInfo { get; set; }
/// <summary>
/// 如果查询没发现排序就将当前配置追加上去
/// </summary>
public bool AppendIfOrderNone => AppendOrder >= 0;
/// <summary>
/// 大于等于0表示需要
/// </summary>
public int AppendOrder { get; set; } = -1;
public string PropertyName { get;}
protected bool Equals(PaginationConfig other)
{
return PropertyName == other.PropertyName;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((PaginationConfig) obj);
}
public override int GetHashCode()
{
return (PropertyName != null ? PropertyName.GetHashCode() : 0);
}
}
}

View File

@ -0,0 +1,27 @@
using System;
namespace ShardingCore.Sharding.PaginationConfigurations
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 01 September 2021 21:27:25
* @Email: 326308290@qq.com
*/
[Flags]
public enum PaginationMatchEnum
{
/// <summary>
/// 必须是当前对象的属性
/// </summary>
Owner = 1,
/// <summary>
/// 只要名称一样就可以了
/// </summary>
Named = 1 << 1,
/// <summary>
/// 仅第一个匹配就可以了
/// </summary>
PrimaryMatch = 1 << 2
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ShardingCore.Sharding.PaginationConfigurations
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 7:45:16
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
/// <summary>
/// 分页配置元数据
/// </summary>
public class PaginationMetadata
{
public ISet<PaginationConfig> PaginationConfigs = new HashSet<PaginationConfig>();
/// <summary>
/// 反向排序因子
/// </summary>
public double ReverseFactor { get; set; } = -1;
/// <summary>
/// 当条数大于多少条后采用反向排序
/// </summary>
public long ReverseTotalGe { get; set; } = 10000L;
/// <summary>
/// 是否已开启反向排序 仅支持单排序
/// </summary>
public bool EnableReverseShardingPage => ReverseFactor > 0 && ReverseFactor < 1 && ReverseTotalGe >= 1000;
/// <summary>
/// 分表发现如果少于多少条后直接取到内存 LESS THAN OR EQUAL
/// </summary>
public int TakeInMemoryCountIfLe { get; set; } = 100;
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace ShardingCore.Sharding.PaginationConfigurations
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 01 September 2021 21:32:53
* @Email: 326308290@qq.com
*/
public class PaginationOrderPropertyBuilder
{
private readonly PaginationConfig _paginationConfig;
public PaginationOrderPropertyBuilder(LambdaExpression orderPropertyExpression,PaginationMetadata metadata)
{
_paginationConfig = new PaginationConfig(orderPropertyExpression);
metadata.PaginationConfigs.Add(_paginationConfig);
}
/// <summary>
/// 使用哪个后缀比较
/// </summary>
/// <param name="tailComparer"></param>
/// <returns></returns>
public PaginationOrderPropertyBuilder UseTailCompare(IComparer<string> tailComparer)
{
_paginationConfig.TailComparer= tailComparer ?? throw new ArgumentException(nameof(tailComparer));
return this;
}
/// <summary>
/// 使用哪种比较方式
/// </summary>
/// <param name="paginationMatchEnum"></param>
/// <returns></returns>
public PaginationOrderPropertyBuilder UseQueryMatch(PaginationMatchEnum paginationMatchEnum)
{
_paginationConfig.PaginationMatchEnum = paginationMatchEnum;
return this;
}
/// <summary>
/// 如果查询没发现排序就将当前配置追加上去
/// </summary>
/// <param name="order">大于等于0生效,越大优先级越高</param>
/// <returns></returns>
public PaginationOrderPropertyBuilder UseAppendIfOrderNone(int order=0)
{
_paginationConfig.AppendOrder = order;
return this;
}
}
}

View File

@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines;
namespace ShardingCore.Sharding.ShardingQueryExecutors
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/1 7:47:05
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class DefaultShardingQueryExecutor : IShardingQueryExecutor
{
private readonly IStreamMergeContextFactory _streamMergeContextFactory;
public DefaultShardingQueryExecutor(IStreamMergeContextFactory streamMergeContextFactory)
{
_streamMergeContextFactory = streamMergeContextFactory;
}
public TResult Execute<TResult>(ICurrentDbContext currentContext, Expression query)
{
var currentDbContext = currentContext.Context;
if (currentDbContext is IShardingDbContext shardingDbContext)
{
//如果根表达式为iqueryable表示需要迭代
if (query.Type.HasImplementedRawGeneric(typeof(IQueryable<>)))
{
return EnumerableExecute<TResult>(shardingDbContext, query, false);
}
return DoExecute<TResult>(shardingDbContext, query, false, default);
}
throw new ShardingCoreException("db context operator is not IShardingDbContext");
}
public TResult ExecuteAsync<TResult>(ICurrentDbContext currentContext, Expression query,CancellationToken cancellationToken = new CancellationToken())
{
var currentDbContext = currentContext.Context;
if (currentDbContext is IShardingDbContext shardingDbContext)
{
if (typeof(TResult).HasImplementedRawGeneric(typeof(IAsyncEnumerable<>)))
{
return EnumerableExecute<TResult>(shardingDbContext, query, true);
}
if (typeof(TResult).HasImplementedRawGeneric(typeof(Task<>)))
{
return DoExecute<TResult>(shardingDbContext, query, true, default);
}
throw new ShardingCoreException($"db context operator not support query expression:[{query.ShardingPrint()}] result type:[{typeof(TResult).FullName}]");
}
throw new ShardingCoreException("db context operator is not IShardingDbContext");
}
private TResult DoExecute<TResult>(IShardingDbContext shardingDbContext, Expression query, bool async, CancellationToken cancellationToken = new CancellationToken())
{
if (query is MethodCallExpression methodCallExpression)
{
switch (methodCallExpression.Method.Name)
{
case nameof(Enumerable.First):
return GenericMergeExecute<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.FirstOrDefault):
return GenericMergeExecute<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Last):
return GenericMergeExecute<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.LastOrDefault):
return GenericMergeExecute<TResult>(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Single):
return GenericMergeExecute<TResult>(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.SingleOrDefault):
return GenericMergeExecute<TResult>(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Count):
return EnsureMergeExecute<TResult>(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.LongCount):
return EnsureMergeExecute<TResult>(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Any):
return EnsureMergeExecute<TResult>(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.All):
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Max):
return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Min):
return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Sum):
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Average):
return EnsureMergeExecute2<TResult>(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Contains):
return EnsureMergeExecute<TResult>(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
}
}
throw new ShardingCoreException($"db context operator not support query expression:[{query.ShardingPrint()}] result type:[{typeof(TResult).FullName}]");
}
private TResult EnumerableExecute<TResult>(IShardingDbContext shardingDbContext, Expression query, bool async)
{
Type queryEntityType;
if (async)
queryEntityType = typeof(TResult).GetGenericArguments()[0];
else
{
queryEntityType = query.Type.GetSequenceType();
}
Type type = typeof(EnumerableQuery<>);
type = type.MakeGenericType(queryEntityType);
var queryable = Activator.CreateInstance(type, query);
var streamMergeContextMethod = _streamMergeContextFactory.GetType().GetMethod("Create");
if (streamMergeContextMethod == null)
throw new ShardingCoreException("cant found IStreamMergeContextFactory method [Create]");
var streamMergeContext = streamMergeContextMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(_streamMergeContextFactory, new[] { queryable, shardingDbContext });
Type streamMergeEngineType = typeof(AsyncEnumerableStreamMergeEngine<>);
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
return (TResult)Activator.CreateInstance(streamMergeEngineType, streamMergeContext);
}
private TResult GenericMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultEntityType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var methodName = async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult);
var streamEngineMethod = streamMergeEngineType.GetMethod(methodName);
if (streamEngineMethod == null)
throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamEngine, @params);
}
private TResult GenericMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType, resultType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var methodName = async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult);
var streamEngineMethod = streamMergeEngineType.GetMethod(methodName);
if (streamEngineMethod == null)
throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
var @params = async ? new object[] { cancellationToken } : new object[0];
//typeof(TResult)==?resultType
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params);
}
private TResult EnsureMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType());
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var methodName = async ? nameof(IEnsureMergeResult<object>.MergeResultAsync) : nameof(IEnsureMergeResult<object>.MergeResult);
var streamEngineMethod = streamMergeEngineType.GetMethod(methodName);
if (streamEngineMethod == null)
throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (TResult)streamEngineMethod.Invoke(streamEngine, @params);
}
private TResult EnsureMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
if (async)
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType(), typeof(TResult).GetGenericArguments()[0]);
else
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType(), typeof(TResult));
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var methodName = async
? nameof(IEnsureMergeResult<object>.MergeResultAsync)
: nameof(IEnsureMergeResult<object>.MergeResult);
var streamEngineMethod = streamMergeEngineType.GetMethod(methodName);
if (streamEngineMethod == null)
throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (TResult)streamEngineMethod.Invoke(streamEngine, @params);
}
}
}

View File

@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.PaginationConfigurations;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
namespace ShardingCore.Sharding.ShardingQueryExecutors
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/8/31 21:30:28
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class EnumeratorShardingQueryExecutor<TEntity>
{
private readonly StreamMergeContext<TEntity> _streamMergeContext;
private readonly IShardingPageManager _shardingPageManager;
private readonly IVirtualTableManager _virtualTableManager;
public EnumeratorShardingQueryExecutor(StreamMergeContext<TEntity> streamMergeContext)
{
_streamMergeContext = streamMergeContext;
_shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
}
public IEnumeratorStreamMergeEngine<TEntity> ExecuteAsync(CancellationToken cancellationToken = new CancellationToken())
{
//操作单表
if (!_streamMergeContext.IsShardingQuery())
{
return new SingleQueryEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext);
}
//未开启系统分表或者本次查询涉及多张分表
if (_streamMergeContext.IsPaginationQuery()&&_streamMergeContext.IsSingleShardingTableQuery()&&_shardingPageManager.Current != null)
{
//获取虚拟表判断是否启用了分页配置
var shardingEntityType = _streamMergeContext.RouteResults.First().ReplaceTables.First().EntityType;
var virtualTable = _virtualTableManager.GetVirtualTable(_streamMergeContext.GetShardingDbContext().ShardingDbContextType, shardingEntityType);
if (virtualTable.EnablePagination)
{
var paginationMetadata = virtualTable.PaginationMetadata;
//判断本次查询的排序是否包含order如果不包含就获取默认添加的排序
if (_streamMergeContext.Orders.IsEmpty())
{
//除了判断属性名还要判断所属关系
var appendPaginationConfig = paginationMetadata.PaginationConfigs.OrderByDescending(o=>o.AppendOrder)
.FirstOrDefault(o => o.AppendIfOrderNone&&typeof(TEntity).ContainPropertyName(o.PropertyName)&& PaginationMatch(o));
if (appendPaginationConfig != null)
{
return new AppenOrderSequenceEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext, appendPaginationConfig, _shardingPageManager.Current.RouteQueryResults);
}
}
else
{
var primaryOrder = _streamMergeContext.Orders.First();
var appendPaginationConfig = paginationMetadata.PaginationConfigs.FirstOrDefault(o => PaginationMatch(o,primaryOrder));
if (appendPaginationConfig != null)
{
return new SequenceEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext, appendPaginationConfig, _shardingPageManager.Current.RouteQueryResults, primaryOrder.IsAsc);
}
if (_streamMergeContext.Orders.Count() == 1)
{
//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, primaryOrder, total);
}
}
}
}
}
}
return new DefaultShardingEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext);
}
private bool PaginationMatch(PaginationConfig paginationConfig)
{
if (paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.Owner)&& !paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.Named))
return typeof(TEntity) == paginationConfig.OrderPropertyInfo.DeclaringType;
return false;
}
private bool PaginationMatch(PaginationConfig paginationConfig,PropertyOrder propertyOrder)
{
if (paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.PrimaryMatch))
{
if (!propertyOrder.PropertyExpression.StartsWith(paginationConfig.PropertyName))
return false;
}
if (propertyOrder.PropertyExpression != paginationConfig.PropertyName)
return false;
if (paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.Owner)&&!paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.Named))
return typeof(TEntity) == paginationConfig.OrderPropertyInfo.DeclaringType;
return false;
}
}
}

View File

@ -31,10 +31,11 @@ namespace ShardingCore.Sharding
//public DataSourceRoutingResult RoutingResult { get; }
public int? Skip { get;}
public int? Take { get; }
public IEnumerable<PropertyOrder> Orders { get;}
public IEnumerable<PropertyOrder> Orders { get; private set; }
public SelectContext SelectContext { get;}
public GroupByContext GroupByContext { get; }
public IEnumerable<RouteResult> RouteResults { get; }
public StreamMergeContext(IQueryable<T> source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IRouteTailFactory routeTailFactory)
{
@ -50,6 +51,7 @@ namespace ShardingCore.Sharding
SelectContext = reWriteResult.SelectContext;
GroupByContext = reWriteResult.GroupByContext;
_reWriteSource = reWriteResult.ReWriteQueryable;
RouteResults = _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(), _source);
}
//public StreamMergeContext(IQueryable<T> source,IEnumerable<RouteResult> routeResults,
// IShardingParallelDbContextFactory shardingParallelDbContextFactory,IShardingScopeFactory shardingScopeFactory)
@ -66,16 +68,15 @@ namespace ShardingCore.Sharding
// GroupByContext = reWriteResult.GroupByContext;
// _reWriteSource = reWriteResult.ReWriteQueryable;
//}
public void ReSetOrders(IEnumerable<PropertyOrder> orders)
{
Orders = orders;
}
public DbContext CreateDbContext(RouteResult routeResult)
{
var routeTail = _routeTailFactory.Create(routeResult);
return _shardingDbContext.GetDbContext(false, routeTail);
}
public IEnumerable<RouteResult> GetRouteResults()
{
return _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(),_source);
}
public IRouteTail Create(RouteResult routeResult)
{
@ -96,6 +97,12 @@ namespace ShardingCore.Sharding
return Skip.HasValue || Take.HasValue;
}
public bool IsPaginationQuery()
{
return Skip.GetValueOrDefault() > 0 || Take.GetValueOrDefault() > 0;
}
public bool HasGroupQuery()
{
return this.GroupByContext.GroupExpression != null;
@ -106,5 +113,10 @@ namespace ShardingCore.Sharding
return this.SelectContext.SelectProperties.Any(o => o.IsAggregateMethod);
}
public IShardingDbContext GetShardingDbContext()
{
return _shardingDbContext;
}
}
}

View File

@ -35,7 +35,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
}
_constantItem = (TEntity)constantExpression.Value;
}
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression)
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> queryable, Expression secondExpression)
{
if (!(secondExpression is ConstantExpression))
{

View File

@ -21,7 +21,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
{
}
public override IQueryable EFQueryAfterFilter<TResult1>(IQueryable<TEntity> queryable)
public override IQueryable DoCombineQueryable<TResult1>(IQueryable<TEntity> queryable)
{
var secondExpression = GetSecondExpression();
if (secondExpression != null)
@ -41,7 +41,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
return queryable;
}
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> _queryable, Expression secondExpression)
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> _queryable, Expression secondExpression)
{
return _queryable;
}

View File

@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
_methodCallExpression = methodCallExpression;
}
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression)
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> queryable, Expression secondExpression)
{
if (secondExpression is UnaryExpression where && where.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, bool>> predicate)
{

View File

@ -20,7 +20,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
{
}
public override IQueryable EFQueryAfterFilter<TResult>(IQueryable<TEntity> queryable)
public override IQueryable DoCombineQueryable<TResult>(IQueryable<TEntity> queryable)
{
var secondExpression = GetSecondExpression();
if (secondExpression != null)
@ -41,7 +41,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
return queryable;
}
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> _queryable, Expression secondExpression)
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> _queryable, Expression secondExpression)
{
return _queryable;
}

View File

@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
_methodCallExpression = methodCallExpression;
}
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression)
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> queryable, Expression secondExpression)
{
if (secondExpression is UnaryExpression where)
{

View File

@ -30,38 +30,43 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
public AbstractInMemoryAsyncMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext)
{
_methodCallExpression = methodCallExpression;
var expression = methodCallExpression.Arguments.FirstOrDefault(o => typeof(IQueryable).IsAssignableFrom(o.Type))
#if !EFCORE2
?? throw new InvalidOperationException(methodCallExpression.Print());
#endif
#if EFCORE2
?? throw new InvalidOperationException(methodCallExpression.ToString());
#endif
_queryable = new EnumerableQuery<TEntity>(expression);
_secondExpression = methodCallExpression.Arguments.FirstOrDefault(o => !typeof(IQueryable).IsAssignableFrom(o.Type));
if (_secondExpression != null)
if (methodCallExpression.Arguments.Count < 1 || methodCallExpression.Arguments.Count > 2)
throw new ArgumentException($"argument count must 1 or 2 :[{methodCallExpression.ShardingPrint()}]");
for (int i = 0; i < methodCallExpression.Arguments.Count; i++)
{
_queryable = ProcessSecondExpression(_queryable, _secondExpression);
}
else
{
if (methodCallExpression.Arguments.Count == 2)
var expression = methodCallExpression.Arguments[i];
if (typeof(IQueryable).IsAssignableFrom(expression.Type))
{
#if !EFCORE2
throw new InvalidOperationException(methodCallExpression.Print());
#endif
#if EFCORE2
throw new InvalidOperationException(methodCallExpression.ToString());
#endif
if (_queryable != null)
throw new ArgumentException(
$"argument found more 1 IQueryable :[{methodCallExpression.ShardingPrint()}]");
_queryable = new EnumerableQuery<TEntity>(expression);
}
else
{
_secondExpression = expression;
}
}
if(_queryable==null)
throw new ArgumentException($"argument not found IQueryable :[{methodCallExpression.ShardingPrint()}]");
if (methodCallExpression.Arguments.Count ==2)
{
if(_secondExpression == null)
throw new InvalidOperationException(methodCallExpression.ShardingPrint());
_queryable = CombineQueryable(_queryable, _secondExpression);
}
_mergeContext = ShardingContainer.GetService<IStreamMergeContextFactory>().Create(_queryable, shardingDbContext);
_parllelDbbContexts = new List<DbContext>();
}
protected abstract IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression);
/// <summary>
/// 合并queryable
/// </summary>
/// <param name="queryable"></param>
/// <param name="secondExpression"></param>
/// <returns></returns>
protected abstract IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> queryable, Expression secondExpression);
private IQueryable CreateAsyncExecuteQueryable<TResult>(RouteResult routeResult)
{
@ -69,13 +74,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<TEntity>) GetStreamMergeContext().GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var newFilterQueryable = EFQueryAfterFilter<TResult>(newQueryable);
return newFilterQueryable;
var newCombineQueryable= DoCombineQueryable<TResult>(newQueryable);
return newCombineQueryable
;
}
public async Task<List<TResult>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery, CancellationToken cancellationToken = new CancellationToken())
public async Task<List<RouteQueryResult<TResult>>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery, CancellationToken cancellationToken = new CancellationToken())
{
var tableResult = _mergeContext.GetRouteResults();
var tableResult = _mergeContext.RouteResults;
var enumeratorTasks = tableResult.Select(routeResult =>
{
return Task.Run(async () =>
@ -83,7 +89,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
try
{
var asyncExecuteQueryable = CreateAsyncExecuteQueryable<TResult>(routeResult);
return await efQuery(asyncExecuteQueryable);
var queryResult= await efQuery(asyncExecuteQueryable);
return new RouteQueryResult<TResult>(routeResult, queryResult);
//}
}
catch (Exception e)
@ -99,7 +106,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
public List<TResult> Execute<TResult>(Func<IQueryable, TResult> efQuery, CancellationToken cancellationToken = new CancellationToken())
{
var tableResult = _mergeContext.GetRouteResults();
var tableResult = _mergeContext.RouteResults;
var enumeratorTasks = tableResult.Select(routeResult =>
{
return Task.Run(() =>
@ -121,7 +128,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
}
public virtual IQueryable EFQueryAfterFilter<TResult>(IQueryable<TEntity> queryable)
public virtual IQueryable DoCombineQueryable<TResult>(IQueryable<TEntity> queryable)
{
return queryable;
}

View File

@ -17,7 +17,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
public interface IInMemoryAsyncMergeEngine<TEntity>
{
StreamMergeContext<TEntity> GetStreamMergeContext();
Task<List<TResult>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery,
Task<List<RouteQueryResult<TResult>>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery,
CancellationToken cancellationToken = new CancellationToken());
}
}

View File

@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureExpressionMergeEngines;
@ -32,120 +33,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
public override TEnsureResult MergeResult()
{
if (typeof(decimal) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<decimal>)queryable).Average());
if (result.IsEmpty())
return default;
var average = result.Sum() / result.Count;
return ConvertSum(average);
}
if (typeof(decimal?) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<decimal?>)queryable).Average()
);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
return ConvertSum(average);
}
if (typeof(int) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<int>)queryable).Average()
);
if (result.IsEmpty())
return default;
var average = result.Sum() / result.Count;
return ConvertSum(average);
}
if (typeof(int?) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<int?>)queryable).Average()
);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
return ConvertSum(average);
}
if (typeof(long) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<long>)queryable).Average()
);
if (result.IsEmpty())
return default;
var average = result.Sum() / result.Count;
return ConvertSum(average);
}
if (typeof(long?) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<long?>)queryable).Average()
);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
return ConvertSum(average);
}
if (typeof(double) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<double>)queryable).Average()
);
var average = result.Sum() / result.Count;
return ConvertSum(average);
}
if (typeof(double?) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<double?>)queryable).Average()
);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
return ConvertSum(average);
}
if (typeof(float) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<float>)queryable).Average()
);
if (result.IsEmpty())
return default;
var average = result.Sum() / result.Count;
return ConvertSum(average);
}
if (typeof(float?) == typeof(TEnsureResult))
{
var result = base.Execute(
queryable => ((IQueryable<float?>)queryable).Average()
);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
return ConvertSum(average);
}
#if !EFCORE2
throw new ShardingCoreException(
$"not support {GetMethodCallExpression().Print()} result {typeof(TEnsureResult)}");
#endif
#if EFCORE2
throw new ShardingCoreException(
$"not support {GetMethodCallExpression()} result {typeof(TEnsureResult)}");
#endif
return AsyncHelper.RunSync(() => MergeResultAsync());
}
public override async Task<TEnsureResult> MergeResultAsync(
@ -158,7 +46,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum() / result.Count;
var average = result.Sum(o=>o.QueryResult) / result.Count;
return ConvertSum(average);
}
@ -169,7 +57,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
var sum = result.Sum(o => o.QueryResult);
var average = sum.HasValue ? sum / result.Count : default;
return ConvertSum(average);
}
@ -180,7 +69,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum() / result.Count;
var average = result.Sum(o => o.QueryResult) / result.Count;
return ConvertSum(average);
}
@ -191,7 +80,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
var sum = result.Sum(o => o.QueryResult);
var average = sum.HasValue ? sum / result.Count : default;
return ConvertSum(average);
}
@ -202,7 +92,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum() / result.Count;
var average = result.Sum(o => o.QueryResult) / result.Count;
return ConvertSum(average);
}
@ -213,7 +103,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
var sum = result.Sum(o => o.QueryResult);
var average = sum.HasValue ? sum / result.Count : default;
return ConvertSum(average);
}
@ -222,7 +113,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(
queryable => ((IQueryable<double>)queryable).AverageAsync(cancellationToken),
cancellationToken);
var average = result.Sum() / result.Count;
var average = result.Sum(o => o.QueryResult) / result.Count;
return ConvertSum(average);
}
@ -233,7 +124,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
var sum = result.Sum(o => o.QueryResult);
var average = sum.HasValue ? sum / result.Count : default;
return ConvertSum(average);
}
@ -244,7 +136,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum() / result.Count;
var average = result.Sum(o => o.QueryResult) / result.Count;
return ConvertSum(average);
}
@ -255,18 +147,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
cancellationToken);
if (result.IsEmpty())
return default;
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
var sum = result.Sum(o => o.QueryResult);
var average = sum.HasValue ? sum / result.Count : default;
return ConvertSum(average);
}
#if !EFCORE2
throw new ShardingCoreException(
$"not support {GetMethodCallExpression().Print()} result {typeof(TEnsureResult)}");
#endif
#if EFCORE2
throw new ShardingCoreException(
$"not support {GetMethodCallExpression()} result {typeof(TEnsureResult)}");
#endif
$"not support {GetMethodCallExpression().ShardingPrint()} result {typeof(TEnsureResult)}");
}
private TEnsureResult ConvertSum<TNumber>(TNumber number)

View File

@ -6,6 +6,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
@ -27,14 +28,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
public override TResult MergeResult<TResult>()
{
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).Max());
return result.Max();
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
}
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).MaxAsync(cancellationToken), cancellationToken);
return result.Max();
return result.Max(o=>o.QueryResult);
}
}
}

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
@ -28,14 +29,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
public override TResult MergeResult<TResult>()
{
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).Min());
return result.Min();
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
}
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).MinAsync(cancellationToken), cancellationToken);
return result.Min();
return result.Min(o=>o.QueryResult);
}
}
}

View File

@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureExpressionMergeEngines;
@ -30,94 +31,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
public override TEnsureResult MergeResult()
{
if (typeof(decimal) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<decimal>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(decimal?) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<decimal?>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(int) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<int>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(int?) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<int?>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(long) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<long>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(long?) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<long?>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(double) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<double>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(double?) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<double?>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(float) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<float>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
if (typeof(float?) == typeof(TEnsureResult))
{
var result = base.Execute(queryable => ((IQueryable<float?>)queryable).Sum());
if (result.IsEmpty())
return default;
var sum = result.Sum();
return ConvertSum(sum);
}
#if !EFCORE2
throw new ShardingCoreException(
$"not support {GetMethodCallExpression().Print()} result {typeof(TEnsureResult)}");
#endif
#if EFCORE2
throw new ShardingCoreException(
$"not support {GetMethodCallExpression()} result {typeof(TEnsureResult)}");
#endif
return AsyncHelper.RunSync(() => MergeResultAsync());
}
public override async Task<TEnsureResult> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
@ -127,7 +42,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<decimal>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o=>o.QueryResult);
return ConvertSum(sum);
}
if (typeof(decimal?) == typeof(TEnsureResult))
@ -135,7 +50,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<decimal?>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o=>o.QueryResult);
return ConvertSum(sum);
}
if (typeof(int) == typeof(TEnsureResult))
@ -143,7 +58,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<int>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o=>o.QueryResult);
return ConvertSum(sum);
}
if (typeof(int?) == typeof(TEnsureResult))
@ -151,7 +66,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<int?>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o => o.QueryResult);
return ConvertSum(sum);
}
if (typeof(long) == typeof(TEnsureResult))
@ -159,7 +74,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<long>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o => o.QueryResult);
return ConvertSum(sum);
}
if (typeof(long?) == typeof(TEnsureResult))
@ -167,7 +82,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<long?>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o => o.QueryResult);
return ConvertSum(sum);
}
if (typeof(double) == typeof(TEnsureResult))
@ -175,7 +90,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<double>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o => o.QueryResult);
return ConvertSum(sum);
}
if (typeof(double?) == typeof(TEnsureResult))
@ -183,7 +98,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<double?>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o => o.QueryResult);
return ConvertSum(sum);
}
if (typeof(float) == typeof(TEnsureResult))
@ -191,7 +106,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<float>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o => o.QueryResult);
return ConvertSum(sum);
}
if (typeof(float?) == typeof(TEnsureResult))
@ -199,18 +114,12 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
var result = await base.ExecuteAsync(queryable => ((IQueryable<float?>)queryable).SumAsync(cancellationToken), cancellationToken);
if (result.IsEmpty())
return default;
var sum = result.Sum();
var sum = result.Sum(o => o.QueryResult);
return ConvertSum(sum);
}
#if !EFCORE2
throw new ShardingCoreException(
$"not support {GetMethodCallExpression().Print()} result {typeof(TEnsureResult)}");
#endif
#if EFCORE2
throw new ShardingCoreException(
$"not support {GetMethodCallExpression()} result {typeof(TEnsureResult)}");
#endif
$"not support {GetMethodCallExpression().ShardingPrint()} result {typeof(TEnsureResult)}");
}
private TEnsureResult ConvertSum<TNumber>(TNumber number)
{

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
@ -29,9 +30,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override bool MergeResult()
{
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).Any());
return result.All(o => o);
return AsyncHelper.RunSync(()=> MergeResultAsync());
}
public override async Task<bool> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
@ -39,7 +38,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).AnyAsync(cancellationToken), cancellationToken);
return result.All(o => o);
return result.All(o => o.QueryResult);
}
}
}

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
@ -29,16 +30,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override bool MergeResult()
{
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).Any());
return result.Any(o => o);
return AsyncHelper.RunSync(() => MergeResultAsync());
}
public override async Task<bool> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).AnyAsync(cancellationToken), cancellationToken);
return result.Any(o => o);
return result.Any(o => o.QueryResult);
}
}

View File

@ -11,6 +11,7 @@ using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.Enumerators.StreamMergeSync;
using ShardingCore.Sharding.ShardingQueryExecutors;
#if EFCORE2
using Microsoft.EntityFrameworkCore.Extensions.Internal;
@ -24,15 +25,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
* @Date: Saturday, 14 August 2021 22:07:28
* @Email: 326308290@qq.com
*/
public class AsyncEnumerableStreamMergeEngine<T> : IAsyncEnumerable<T>, IEnumerable<T>, IDisposable
public class AsyncEnumerableStreamMergeEngine<T> : IAsyncEnumerable<T>, IEnumerable<T>
{
private readonly StreamMergeContext<T> _mergeContext;
private readonly ICollection<DbContext> _parllelDbbContexts;
public AsyncEnumerableStreamMergeEngine(StreamMergeContext<T> mergeContext)
{
_mergeContext = mergeContext;
_parllelDbbContexts = new LinkedList<DbContext>();
}
@ -44,7 +43,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
await enumator.MoveNextAsync();
return enumator;
}
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
{
return new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync(cancellationToken)
.GetAsyncEnumerator(cancellationToken);
}
#endif
#if EFCORE2
private async Task<IAsyncEnumerator<T>> GetAsyncEnumerator(IQueryable<T> newQueryable)
{
@ -52,62 +57,12 @@ namespace ShardingCore.Sharding.StreamMergeEngines
await enumator.MoveNext();
return enumator;
}
#endif
#if !EFCORE2
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
{
return GetShardingEnumerator();
}
#endif
#if EFCORE2
IAsyncEnumerator<T> IAsyncEnumerable<T>.GetEnumerator()
{
return GetShardingEnumerator();
}
#endif
private IQueryable<T> CreateAsyncExecuteQueryable(RouteResult routeResult,int routeCount)
{
var shardingDbContext = _mergeContext.CreateDbContext(routeResult);
var useOriginal = routeCount>1;
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<T>)(useOriginal?_mergeContext.GetReWriteQueryable():_mergeContext.GetOriginalQueryable())
.ReplaceDbContextQueryable(shardingDbContext);
return newQueryable;
}
private IAsyncEnumerator<T> GetShardingEnumerator()
{
var tableResult = _mergeContext.GetRouteResults();
var routeCount = tableResult.Count();
var enumeratorTasks = tableResult.Select(routeResult =>
{
return Task.Run(async () =>
{
try
{
var newQueryable = CreateAsyncExecuteQueryable(routeResult, routeCount);
var asyncEnumerator = await GetAsyncEnumerator(newQueryable);
return new StreamMergeAsyncEnumerator<T>(asyncEnumerator);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}).ToArray();
var streamEnumerators = Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult();
if (routeCount>1&&_mergeContext.HasSkipTake())
return new PaginationStreamMergeAsyncEnumerator<T>(_mergeContext, streamEnumerators);
if (_mergeContext.HasGroupQuery())
return new MultiAggregateOrderStreamMergeAsyncEnumerator<T>(_mergeContext, streamEnumerators);
return new MultiOrderStreamMergeAsyncEnumerator<T>(_mergeContext, streamEnumerators);
}
private IEnumerator<T> GetEnumerator(IQueryable<T> newQueryable)
@ -119,33 +74,9 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public IEnumerator<T> GetEnumerator()
{
var tableResult = _mergeContext.GetRouteResults();
var routeCount = tableResult.Count();
var enumeratorTasks = tableResult.Select(routeResult =>
{
return Task.Run(() =>
{
try
{
var newQueryable = CreateAsyncExecuteQueryable(routeResult, routeCount);
var enumerator = GetEnumerator(newQueryable);
return new StreamMergeEnumerator<T>(enumerator);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}).ToArray();
var streamEnumerators = Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult();
if (routeCount > 1 && _mergeContext.HasSkipTake())
return new PaginationStreamMergeEnumerator<T>(_mergeContext, streamEnumerators);
if (_mergeContext.HasGroupQuery())
return new MultiAggregateOrderStreamMergeEnumerator<T>(_mergeContext, streamEnumerators);
return new MultiOrderStreamMergeEnumerator<T>(_mergeContext, streamEnumerators);
return new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync()
.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
@ -153,22 +84,5 @@ namespace ShardingCore.Sharding.StreamMergeEngines
return GetEnumerator();
}
public void Dispose()
{
if (_parllelDbbContexts.IsNotEmpty())
{
_parllelDbbContexts.ForEach(o =>
{
try
{
o.Dispose();
}
catch (Exception e)
{
Console.WriteLine(e);
}
});
}
}
}
}

View File

@ -4,6 +4,7 @@ using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureExpressionMergeEngines;
@ -25,16 +26,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override bool MergeResult()
{
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).Contains(GetConstantItem()));
return result.Any(o => o);
return AsyncHelper.RunSync(() => MergeResultAsync());
}
public override async Task<bool> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).ContainsAsync(GetConstantItem(), cancellationToken), cancellationToken);
return result.Any(o => o);
return result.Any(o => o.QueryResult);
}
}

View File

@ -1,10 +1,11 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureExpressionMergeEngines;
namespace ShardingCore.Sharding.StreamMergeEngines
@ -18,22 +19,29 @@ namespace ShardingCore.Sharding.StreamMergeEngines
*/
public class CountAsyncInMemoryMergeEngine<TEntity> : AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine<TEntity,int>
{
private readonly IShardingPageManager _shardingPageManager;
public CountAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{
_shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
}
public override int MergeResult()
{
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).Count());
return result.Sum();
return AsyncHelper.RunSync(() => MergeResultAsync());
}
public override async Task<int> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).CountAsync(cancellationToken), cancellationToken);
return result.Sum();
if (_shardingPageManager.Current != null)
{
foreach (var routeQueryResult in result)
{
_shardingPageManager.Current.RouteQueryResults.Add(new RouteQueryResult<long>(routeQueryResult.RouteResult, routeQueryResult.QueryResult));
}
}
return result.Sum(o=>o.QueryResult);
}
}

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 15:38:05
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public abstract class AbstractEnumeratorAsyncStreamMergeEngine<TEntity>: AbstractEnumeratorStreamMergeEngine<TEntity>
{
public AbstractEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
{
}
public override IAsyncEnumerator<TEntity> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
{
var dbStreamMergeAsyncEnumerators = GetDbStreamMergeAsyncEnumerators();
if (dbStreamMergeAsyncEnumerators.IsEmpty())
throw new ShardingCoreException("GetDbStreamMergeAsyncEnumerators empty");
return GetStreamMergeAsyncEnumerator(dbStreamMergeAsyncEnumerators);
}
public abstract IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators();
public abstract IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators);
public async Task<IAsyncEnumerator<TEntity>> DoGetAsyncEnumerator(IQueryable<TEntity> newQueryable)
{
var enumator = newQueryable.AsAsyncEnumerable().GetAsyncEnumerator();
await enumator.MoveNextAsync();
return enumator;
}
// public virtual IQueryable<TEntity> CreateAsyncExecuteQueryable(RouteResult routeResult)
// {
// var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
// var useOriginal = StreamMergeContext > 1;
// DbContextQueryStore.TryAdd(routeResult,shardingDbContext);
// var newQueryable = (IQueryable<TEntity>)(useOriginal ? StreamMergeContext.GetReWriteQueryable() : StreamMergeContext.GetOriginalQueryable())
// .ReplaceDbContextQueryable(shardingDbContext);
// return newQueryable;
// }
public override IEnumerator<TEntity> GetEnumerator()
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,52 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 15:35:39
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public abstract class AbstractEnumeratorStreamMergeEngine<TEntity>:IEnumeratorStreamMergeEngine<TEntity>
{
public StreamMergeContext<TEntity> StreamMergeContext { get; }
public ConcurrentDictionary<RouteResult,DbContext> DbContextQueryStore { get; }
public AbstractEnumeratorStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext)
{
StreamMergeContext = streamMergeContext;
DbContextQueryStore = new ConcurrentDictionary<RouteResult, DbContext>();
}
public abstract IAsyncEnumerator<TEntity> GetAsyncEnumerator(
CancellationToken cancellationToken = new CancellationToken());
public abstract IEnumerator<TEntity> GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Dispose()
{
if (DbContextQueryStore.IsNotEmpty())
{
DbContextQueryStore.Values.ForEach(dbContext =>
{
dbContext.Dispose();
});
}
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 15:38:13
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class AbstractEnumeratorSyncStreamMergeEngine<TEntity> : AbstractEnumeratorStreamMergeEngine<TEntity>
{
public AbstractEnumeratorSyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
{
}
public override IAsyncEnumerator<TEntity> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
{
throw new NotImplementedException();
}
public override IEnumerator<TEntity> GetEnumerator()
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 15:15:34
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public interface IEnumeratorStreamMergeEngine<TEntity> : IAsyncEnumerable<TEntity>, IEnumerable<TEntity>, IDisposable
{
}
}

View File

@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.PaginationConfigurations;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Base;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 8:09:18
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class AppenOrderSequenceEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
{
private readonly PaginationConfig _appendPaginationConfig;
private readonly ICollection<RouteQueryResult<long>> _routeQueryResults;
private IShardingPageManager _shardingPageManager;
private IVirtualTableManager _virtualTableManager;
public AppenOrderSequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PaginationConfig appendPaginationConfig, ICollection<RouteQueryResult<long>> routeQueryResults) : base(streamMergeContext)
{
_appendPaginationConfig = appendPaginationConfig;
_routeQueryResults = routeQueryResults;
_shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
}
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
{
var noPaginationQueryable = StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake();
var skip = StreamMergeContext.Skip.GetValueOrDefault();
if (skip < 0)
throw new ShardingCoreException("skip must ge 0");
var take = StreamMergeContext.Take;
if (take.HasValue&&take.Value <= 0)
throw new ShardingCoreException("take must gt 0");
var sortRouteResults = _routeQueryResults.Select(o => new
{
Tail = o.RouteResult.ReplaceTables.First().Tail,
RouteQueryResult = o
}).OrderBy(o => o.Tail, _appendPaginationConfig.TailComparer).ToList();
var skipCount = skip;
var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o=>o.RouteQueryResult)).Skip(skip).Take(take).ToList();
StreamMergeContext.ReSetOrders(new PropertyOrder[] { new PropertyOrder(_appendPaginationConfig.PropertyName, true) });
var enumeratorTasks = sequenceResults.Select(sequenceResult =>
{
var newQueryable = CreateAsyncExecuteQueryable(noPaginationQueryable, sequenceResult);
return Task.Run(async () =>
{
try
{
var asyncEnumerator = await DoGetAsyncEnumerator(newQueryable);
return new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}).ToArray();
var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException();
return streamEnumerators;
}
private IQueryable<TEntity> CreateAsyncExecuteQueryable(IQueryable<TEntity> noPaginationQueryable, SequenceResult sequenceResult)
{
var shardingDbContext = StreamMergeContext.CreateDbContext(sequenceResult.RouteResult);
DbContextQueryStore.TryAdd(sequenceResult.RouteResult, shardingDbContext);
var newQueryable = (IQueryable<TEntity>)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take).OrderWithExpression(new PropertyOrder[]{new PropertyOrder(_appendPaginationConfig.PropertyName,true)}))
.ReplaceDbContextQueryable(shardingDbContext);
return newQueryable;
}
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
{
if (StreamMergeContext.HasGroupQuery())
return new MultiAggregateOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
}
}
}

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Base
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 8:31:20
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class SequencePaginationList
{
private readonly IEnumerable<RouteQueryResult<long>> _routeQueryResults;
private long? _skip;
private long? _take;
public SequencePaginationList(IEnumerable<RouteQueryResult<long>> routeQueryResults)
{
_routeQueryResults = routeQueryResults;
}
public SequencePaginationList Skip(long? skip)
{
_skip = skip;
return this;
}
public SequencePaginationList Take(long? take)
{
_take = take;
return this;
}
public ICollection<SequenceResult> ToList()
{
ICollection<SequenceResult> routeResults = new LinkedList<SequenceResult>();
var currentSkip = _skip.GetValueOrDefault();
var currentTake = _take;
bool stopSkip = false;
bool needBreak = false;
foreach (var routeQueryResult in _routeQueryResults)
{
if (!stopSkip)
{
if (routeQueryResult.QueryResult >= currentSkip)
{
stopSkip = true;
}
else
{
currentSkip = currentSkip - routeQueryResult.QueryResult;
continue;
}
}
var currentRealSkip = currentSkip;
var currentRealTake = routeQueryResult.QueryResult-currentSkip;
if (currentSkip != 0)
currentSkip = 0;
if (currentTake.HasValue)
{
if (currentTake.Value <= currentRealTake)
{
currentRealTake = currentTake.Value;
needBreak = true;
}
else
{
currentRealTake = currentTake.Value-currentRealTake;
}
}
var sequenceResult = new SequenceResult(currentRealSkip, currentRealTake, routeQueryResult.RouteResult);
routeResults.Add(sequenceResult);
if (needBreak)
break;
}
return routeResults;
}
}
public class SequenceResult
{
public SequenceResult(long skip, long take, RouteResult routeResult)
{
Skip = (int)skip;
Take = (int)take;
RouteResult = routeResult;
}
public int Skip { get; }
public int Take { get; }
public RouteResult RouteResult { get; }
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 16:16:12
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class DefaultShardingEnumeratorAsyncStreamMergeEngine<TEntity>:AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
{
public DefaultShardingEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
{
}
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
{
var tableResult = StreamMergeContext.RouteResults;
var enumeratorTasks = tableResult.Select(routeResult =>
{
var newQueryable = CreateAsyncExecuteQueryable(routeResult);
return Task.Run(async () =>
{
try
{
var asyncEnumerator = await DoGetAsyncEnumerator(newQueryable);
return new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}).ToArray();
var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException();
return streamEnumerators;
}
private IQueryable<TEntity> CreateAsyncExecuteQueryable(RouteResult routeResult)
{
var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
DbContextQueryStore.TryAdd(routeResult, shardingDbContext);
var newQueryable = (IQueryable<TEntity>)StreamMergeContext.GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
return newQueryable;
}
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
{
if (StreamMergeContext.IsPaginationQuery())
return new PaginationStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
if (StreamMergeContext.HasGroupQuery())
return new MultiAggregateOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
}
}
}

View File

@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Core.Internal.Visitors;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 13:32:12
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ReverseShardingEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
{
private readonly PropertyOrder _primaryOrder;
private readonly long _total;
public ReverseShardingEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PropertyOrder primaryOrder, long total) : base(streamMergeContext)
{
_primaryOrder = primaryOrder;
_total = total;
}
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
{
var noPaginationNoOrderQueryable = _primaryOrder.IsAsc ? StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake().RemoveOrderBy(): StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake().RemoveOrderByDescending();
var skip = StreamMergeContext.Skip.GetValueOrDefault();
var take = StreamMergeContext.Take.GetValueOrDefault();
var realSkip = _total- take- skip;
var tableResult = StreamMergeContext.RouteResults;
var reverseOrderQueryable = noPaginationNoOrderQueryable.Skip((int)realSkip).Take((int)realSkip+take).OrderWithExpression(new List<PropertyOrder>()
{
new PropertyOrder( _primaryOrder.PropertyExpression,!_primaryOrder.IsAsc)
});
var enumeratorTasks = tableResult.Select(routeResult =>
{
var newQueryable = CreateAsyncExecuteQueryable(reverseOrderQueryable,routeResult);
return Task.Run(async () =>
{
try
{
var asyncEnumerator = await DoGetAsyncEnumerator(newQueryable);
return new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}).ToArray();
var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException();
return streamEnumerators;
}
private IQueryable<TEntity> CreateAsyncExecuteQueryable(IQueryable<TEntity> reverseOrderQueryable, RouteResult routeResult)
{
var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
DbContextQueryStore.TryAdd(routeResult, shardingDbContext);
var newQueryable = (IQueryable<TEntity>)reverseOrderQueryable
.ReplaceDbContextQueryable(shardingDbContext);
return newQueryable;
}
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
{
var doGetStreamMergeAsyncEnumerator = DoGetStreamMergeAsyncEnumerator(streamsAsyncEnumerators);
return new InMemoryReverseStreamMergeAsyncEnumerator<TEntity>(doGetStreamMergeAsyncEnumerator);
}
private IStreamMergeAsyncEnumerator<TEntity> DoGetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
{
if (StreamMergeContext.IsPaginationQuery())
return new PaginationStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
if (StreamMergeContext.HasGroupQuery())
return new MultiAggregateOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
}
}
}

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.Internal.Visitors;
using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.PaginationConfigurations;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Base;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/2 16:29:06
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class SequenceEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
{
private readonly PaginationConfig _orderPaginationConfig;
private readonly ICollection<RouteQueryResult<long>> _routeQueryResults;
private readonly bool _isAsc;
public SequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PaginationConfig orderPaginationConfig, ICollection<RouteQueryResult<long>> routeQueryResults, bool isAsc) : base(streamMergeContext)
{
_orderPaginationConfig = orderPaginationConfig;
_routeQueryResults = routeQueryResults;
_isAsc = isAsc;
}
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
{
var noPaginationQueryable = StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake();
var skip = StreamMergeContext.Skip.GetValueOrDefault();
if (skip < 0)
throw new ShardingCoreException("skip must ge 0");
var take = StreamMergeContext.Take;
if (take.HasValue && take.Value <= 0)
throw new ShardingCoreException("take must gt 0");
var sortRouteResults = _routeQueryResults.Select(o => new
{
Tail = o.RouteResult.ReplaceTables.First().Tail,
RouteQueryResult = o
}).OrderByIf(o => o.Tail, _isAsc, _orderPaginationConfig.TailComparer)
.OrderByDescendingIf(o => o.Tail, !_isAsc, _orderPaginationConfig.TailComparer).ToList();
var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o => o.RouteQueryResult)).Skip(skip).Take(take).ToList();
var enumeratorTasks = sequenceResults.Select(sequenceResult =>
{
var newQueryable = CreateAsyncExecuteQueryable(noPaginationQueryable, sequenceResult);
return Task.Run(async () =>
{
try
{
var asyncEnumerator = await DoGetAsyncEnumerator(newQueryable);
return new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}).ToArray();
var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException();
return streamEnumerators;
}
private IQueryable<TEntity> CreateAsyncExecuteQueryable(IQueryable<TEntity> noPaginationQueryable, SequenceResult sequenceResult)
{
var shardingDbContext = StreamMergeContext.CreateDbContext(sequenceResult.RouteResult);
DbContextQueryStore.TryAdd(sequenceResult.RouteResult, shardingDbContext);
var newQueryable = (IQueryable<TEntity>)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take))
.ReplaceDbContextQueryable(shardingDbContext);
return newQueryable;
}
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
{
if (StreamMergeContext.HasGroupQuery())
return new MultiAggregateOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
}
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
{
/*
* @Author: xjm
* @Description:
* @Date: Thursday, 02 September 2021 20:58:10
* @Email: 326308290@qq.com
*/
public class SingleQueryEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
{
public SingleQueryEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
{
}
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
{
var routeResult = StreamMergeContext.RouteResults.First();
var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
DbContextQueryStore.TryAdd(routeResult, shardingDbContext);
var newQueryable = (IQueryable<TEntity>) StreamMergeContext.GetOriginalQueryable().ReplaceDbContextQueryable(shardingDbContext);
var asyncEnumerator = DoGetAsyncEnumerator(newQueryable).WaitAndUnwrapException();
return new[] {new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator)};
}
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
{
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
}
}
}

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
@ -28,20 +29,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override TResult MergeResult<TResult>()
{
var result = base.Execute(queryable => ((IQueryable<TResult>)queryable).First());
var q = result.Where(o => o != null).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).First();
return q.First();
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
}
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).FirstAsync(cancellationToken), cancellationToken);
var q = result.Where(o => o != null).AsQueryable();
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())

View File

@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
@ -31,20 +32,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override TResult MergeResult<TResult>()
{
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).FirstOrDefault());
var q = result.Where(o => o != null).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).FirstOrDefault();
return q.FirstOrDefault();
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
}
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).FirstOrDefaultAsync(cancellationToken), cancellationToken);
var q = result.Where(o => o != null).AsQueryable();
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
@ -28,21 +29,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override TResult MergeResult<TResult>()
{
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).Last());
var q = result.Where(o => o != null).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).Last();
return q.Last();
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
}
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).LastAsync(cancellationToken), cancellationToken);
var q = result.Where(o => o != null).AsQueryable();
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
@ -28,20 +29,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override TResult MergeResult<TResult>()
{
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).LastOrDefault());
var q = result.Where(o => o != null).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).LastOrDefault();
return q.LastOrDefault();
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
}
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).LastOrDefaultAsync(cancellationToken), cancellationToken);
var q = result.Where(o => o != null).AsQueryable();
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())

View File

@ -7,7 +7,9 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Exceptions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
@ -24,16 +26,15 @@ namespace ShardingCore.Sharding.StreamMergeEngines
*/
public class LongCountAsyncInMemoryMergeEngine<TEntity> : AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine<TEntity,long>
{
private readonly IShardingPageManager _shardingPageManager;
public LongCountAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{
_shardingPageManager= ShardingContainer.GetService<IShardingPageManager>();
}
public override long MergeResult()
{
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).LongCount());
return result.Sum();
return AsyncHelper.RunSync(() => MergeResultAsync());
}
public override async Task<long> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
@ -41,7 +42,15 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).LongCountAsync(cancellationToken), cancellationToken);
return result.Sum();
if (_shardingPageManager.Current != null)
{
foreach (var routeQueryResult in result)
{
_shardingPageManager.Current.RouteQueryResults.Add(routeQueryResult);
}
}
return result.Sum(o=>o.QueryResult);
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
namespace ShardingCore.Sharding.StreamMergeEngines
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/1 13:13:17
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class RouteQueryResult<TResult>
{
public RouteResult RouteResult { get; }
public TResult QueryResult { get; }
public RouteQueryResult(RouteResult routeResult,TResult queryResult)
{
RouteResult = routeResult;
QueryResult = queryResult;
}
}
}

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
@ -28,20 +29,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override TResult MergeResult<TResult>()
{
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).Single());
var q = result.Where(o => o != null).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).Single();
return q.Single();
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
}
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).SingleAsync(cancellationToken), cancellationToken);
var q = result.Where(o => o != null).AsQueryable();
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())

View File

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
@ -28,20 +29,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
public override TResult MergeResult<TResult>()
{
var result = base.Execute(queryable => ((IQueryable<TResult>)queryable).SingleOrDefault());
var q = result.Where(o => o != null).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())
return q.OrderWithExpression(streamMergeContext.Orders).SingleOrDefault();
return q.SingleOrDefault();
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
}
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
{
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).SingleOrDefaultAsync(cancellationToken), cancellationToken);
var q = result.Where(o => o != null).AsQueryable();
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
var streamMergeContext = GetStreamMergeContext();
if (streamMergeContext.Orders.Any())

View File

@ -1,3 +1,5 @@
using System;
namespace ShardingCore.Core.Internal.Visitors
{
/*

View File

@ -48,11 +48,11 @@ namespace ShardingCore.Core.Internal.Visitors
var method = methodCallExpression.Method;
if (method.Name == nameof(Queryable.Count) || method.Name == nameof(Queryable.Sum) || method.Name == nameof(Queryable.Max) || method.Name == nameof(Queryable.Min) || method.Name == nameof(Queryable.Average))
{
_selectContext.SelectProperties.Add(new SelectProperty(node.Members[i].Name,true,method.Name));
_selectContext.SelectProperties.Add(new SelectProperty(node.Members[i].DeclaringType, node.Members[i].Name,true,method.Name));
continue;
}
}
_selectContext.SelectProperties.Add(new SelectProperty(node.Members[i].Name,false,string.Empty));
_selectContext.SelectProperties.Add(new SelectProperty(node.Members[i].DeclaringType, node.Members[i].Name,false,string.Empty));
}
return base.VisitNew(node);
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace ShardingCore.Sharding.Visitors
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 15:05:27
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
internal class RemoveOrderByDescendingVisitor : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == nameof(Queryable.OrderByDescending))
return base.Visit(node.Arguments[0]);
return base.VisitMethodCall(node);
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace ShardingCore.Sharding.Visitors
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/3 15:04:25
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
internal class RemoveOrderByVisitor : ExpressionVisitor
{
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.Name == nameof(Queryable.OrderBy))
return base.Visit(node.Arguments[0]);
return base.VisitMethodCall(node);
}
}
}

View File

@ -10,13 +10,14 @@ namespace ShardingCore.Core.Internal.Visitors.Selects
*/
public class SelectProperty
{
public SelectProperty(string propertyName,bool isAggregateMethod,string aggregateMethod)
public SelectProperty( Type ownerType,string propertyName,bool isAggregateMethod,string aggregateMethod)
{
OwnerType = ownerType;
PropertyName = propertyName;
IsAggregateMethod = isAggregateMethod;
AggregateMethod = aggregateMethod;
}
public Type OwnerType { get; }
public string PropertyName { get; }
public bool IsAggregateMethod { get; }
public string AggregateMethod { get; }

View File

@ -15,7 +15,7 @@ namespace ShardingCore
/// </summary>
/// <param name="total">总记录数。</param>
/// <param name="data">当前页面的数据。</param>
public ShardingPagedResult(List<T> data, int total)
public ShardingPagedResult(List<T> data, long total)
{
this.Total = total;
this.Data = data;
@ -26,7 +26,7 @@ namespace ShardingCore
/// <summary>
/// 获取或设置总记录数。
/// </summary>
public int Total { get; set; }
public long Total { get; set; }
/// <summary>
/// 分页数据
/// </summary>