diff --git a/samples/Sample.SqlServer/Controllers/ValuesController.cs b/samples/Sample.SqlServer/Controllers/ValuesController.cs index d6d37b41..518f37e1 100644 --- a/samples/Sample.SqlServer/Controllers/ValuesController.cs +++ b/samples/Sample.SqlServer/Controllers/ValuesController.cs @@ -58,15 +58,15 @@ namespace Sample.SqlServer.Controllers - var sresultx11231 = _defaultTableDbContext.Set().Where(o => o.Age == 198198).Select(o => o.Id).Contains("1981"); - var sresultx1121 = _defaultTableDbContext.Set().Where(o => o.Id == "198").Sum(o => o.Age); - var sresultx111 = _defaultTableDbContext.Set().FirstOrDefault(o => o.Id == "198"); - var sresultx2 = _defaultTableDbContext.Set().Count(o => o.Age <= 10); - var sresultx = _defaultTableDbContext.Set().Where(o => o.Id == "198").FirstOrDefault(); - var sresultx33 = _defaultTableDbContext.Set().Where(o => o.Id == "198").Select(o => o.Id).FirstOrDefault(); - var sresultxc = _defaultTableDbContext.Set().Where(o => o.Id == "198").Select(o => o.Id).ToList(); - var sresultxasdc = _defaultTableDbContext.Set().Where(o => o.Id == "198").ToList(); - var sresult = _defaultTableDbContext.Set().ToList(); + //var sresultx11231 = _defaultTableDbContext.Set().Where(o => o.Age == 198198).Select(o => o.Id).Contains("1981"); + //var sresultx1121 = _defaultTableDbContext.Set().Where(o => o.Id == "198").Sum(o => o.Age); + //var sresultx111 = _defaultTableDbContext.Set().FirstOrDefault(o => o.Id == "198"); + //var sresultx2 = _defaultTableDbContext.Set().Count(o => o.Age <= 10); + //var sresultx = _defaultTableDbContext.Set().Where(o => o.Id == "198").FirstOrDefault(); + //var sresultx33 = _defaultTableDbContext.Set().Where(o => o.Id == "198").Select(o => o.Id).FirstOrDefault(); + //var sresultxc = _defaultTableDbContext.Set().Where(o => o.Id == "198").Select(o => o.Id).ToList(); + //var sresultxasdc = _defaultTableDbContext.Set().Where(o => o.Id == "198").ToList(); + //var sresult = _defaultTableDbContext.Set().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 Get1([FromQuery] int p,[FromQuery]int s) + { + var shardingPageResultAsync = await _defaultTableDbContext.Set().OrderByDescending(o=>o.DateOfMonth).ToShardingPageAsync(p, s); + return Ok(shardingPageResultAsync); + } } } \ No newline at end of file diff --git a/samples/Sample.SqlServer/DIExtension.cs b/samples/Sample.SqlServer/DIExtension.cs index 7f317646..43d6a1e7 100644 --- a/samples/Sample.SqlServer/DIExtension.cs +++ b/samples/Sample.SqlServer/DIExtension.cs @@ -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(); + var virtualDbContext = scope.ServiceProvider.GetService(); if (!virtualDbContext.Set().Any()) { var ids = Enumerable.Range(1, 1000); var userMods = new List(); + var userSalaries = new List(); var SysTests = new List(); + 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(); } } diff --git a/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs b/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs index be0a006f..6d71a66f 100644 --- a/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs +++ b/samples/Sample.SqlServer/DbContexts/DefaultShardingDbContext.cs @@ -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(); diff --git a/samples/Sample.SqlServer/DbContexts/DefaultTableDbContext.cs b/samples/Sample.SqlServer/DbContexts/DefaultTableDbContext.cs index 81d24db0..d637b1cb 100644 --- a/samples/Sample.SqlServer/DbContexts/DefaultTableDbContext.cs +++ b/samples/Sample.SqlServer/DbContexts/DefaultTableDbContext.cs @@ -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; } diff --git a/samples/Sample.SqlServer/Domain/Entities/SysUserMod.cs b/samples/Sample.SqlServer/Domain/Entities/SysUserMod.cs index 82e65940..3fb0f392 100644 --- a/samples/Sample.SqlServer/Domain/Entities/SysUserMod.cs +++ b/samples/Sample.SqlServer/Domain/Entities/SysUserMod.cs @@ -27,5 +27,6 @@ namespace Sample.SqlServer.Domain.Entities /// 用户姓名 /// public int Age { get; set; } + public int AgeGroup { get; set; } } } \ No newline at end of file diff --git a/samples/Sample.SqlServer/Domain/Entities/SysUserSalary.cs b/samples/Sample.SqlServer/Domain/Entities/SysUserSalary.cs new file mode 100644 index 00000000..ed48f076 --- /dev/null +++ b/samples/Sample.SqlServer/Domain/Entities/SysUserSalary.cs @@ -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; } + /// + /// 每月的金额 + /// + [ShardingTableKey] + public int DateOfMonth { get; set; } + /// + /// 工资 + /// + public int Salary { get; set; } + /// + /// 工资 + /// + public long SalaryLong { get; set; } + + /// + /// 工资 + /// + public decimal SalaryDecimal { get; set; } + /// + /// 工资 + /// + public double SalaryDouble { get; set; } + /// + /// 工资 + /// + public float SalaryFloat { get; set; } + } +} \ No newline at end of file diff --git a/samples/Sample.SqlServer/Domain/Maps/SysUserSalaryMap.cs b/samples/Sample.SqlServer/Domain/Maps/SysUserSalaryMap.cs new file mode 100644 index 00000000..287c3975 --- /dev/null +++ b/samples/Sample.SqlServer/Domain/Maps/SysUserSalaryMap.cs @@ -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 + { + public void Configure(EntityTypeBuilder 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)); + } + } +} \ No newline at end of file diff --git a/samples/Sample.SqlServer/Shardings/SysUserModPaginationConfiguration.cs b/samples/Sample.SqlServer/Shardings/SysUserModPaginationConfiguration.cs new file mode 100644 index 00000000..1c4ad58b --- /dev/null +++ b/samples/Sample.SqlServer/Shardings/SysUserModPaginationConfiguration.cs @@ -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 + { + public void Configure(PaginationBuilder builder) + { + builder.PaginationSequence(o => o.Id) + .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch); + } + } +} diff --git a/samples/Sample.SqlServer/Shardings/SysUserModVirtualTableRoute.cs b/samples/Sample.SqlServer/Shardings/SysUserModVirtualTableRoute.cs index d7667d37..24f85717 100644 --- a/samples/Sample.SqlServer/Shardings/SysUserModVirtualTableRoute.cs +++ b/samples/Sample.SqlServer/Shardings/SysUserModVirtualTableRoute.cs @@ -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 CreatePaginationConfiguration() + { + return new SysUserModPaginationConfiguration(); + } } } \ No newline at end of file diff --git a/samples/Sample.SqlServer/Shardings/SysUserSalaryPaginationConfiguration.cs b/samples/Sample.SqlServer/Shardings/SysUserSalaryPaginationConfiguration.cs new file mode 100644 index 00000000..b215a245 --- /dev/null +++ b/samples/Sample.SqlServer/Shardings/SysUserSalaryPaginationConfiguration.cs @@ -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 + { + public void Configure(PaginationBuilder 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(); + } + } +} diff --git a/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs b/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs new file mode 100644 index 00000000..d850c45e --- /dev/null +++ b/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs @@ -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 + { + 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 GetAllTails() + { + var beginTime = new DateTime(2020, 1, 1); + var endTime = new DateTime(2021, 12, 1); + var list = new List(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> 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 CreatePaginationConfiguration() + { + return new SysUserSalaryPaginationConfiguration(); + } + } +} \ No newline at end of file diff --git a/samples/Sample.SqlServer/Startup.cs b/samples/Sample.SqlServer/Startup.cs index 05b33da7..33791e3c 100644 --- a/samples/Sample.SqlServer/Startup.cs +++ b/samples/Sample.SqlServer/Startup.cs @@ -38,7 +38,9 @@ namespace Sample.SqlServer //.ReplaceService()//支持sqlserver2008r2 );//使用链接字符串创建dbcontext op.AddShardingTableRoute(); + op.AddShardingTableRoute(); }); + ////不支持MARS不支持追踪的 //services.AddShardingDbContext(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx2;Integrated Security=True;") // , op => diff --git a/samples/Samples.AutoByDate.SqlServer/DbContexts/DefaultShardingDbContext.cs b/samples/Samples.AutoByDate.SqlServer/DbContexts/DefaultShardingDbContext.cs index 91ba38af..f34e8907 100644 --- a/samples/Samples.AutoByDate.SqlServer/DbContexts/DefaultShardingDbContext.cs +++ b/samples/Samples.AutoByDate.SqlServer/DbContexts/DefaultShardingDbContext.cs @@ -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(); diff --git a/samples/Samples.AutoByDate.SqlServer/DbContexts/DefaultTableDbContext.cs b/samples/Samples.AutoByDate.SqlServer/DbContexts/DefaultTableDbContext.cs index 0058c8ab..a8fd4906 100644 --- a/samples/Samples.AutoByDate.SqlServer/DbContexts/DefaultTableDbContext.cs +++ b/samples/Samples.AutoByDate.SqlServer/DbContexts/DefaultTableDbContext.cs @@ -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; } diff --git a/samples/Samples.AutoByDate.SqlServer/Domain/Entities/TestLogByWeek.cs b/samples/Samples.AutoByDate.SqlServer/Domain/Entities/TestLogByWeek.cs new file mode 100644 index 00000000..d5b78c00 --- /dev/null +++ b/samples/Samples.AutoByDate.SqlServer/Domain/Entities/TestLogByWeek.cs @@ -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; } + } +} diff --git a/samples/Samples.AutoByDate.SqlServer/Domain/Maps/TestLogByWeekMap.cs b/samples/Samples.AutoByDate.SqlServer/Domain/Maps/TestLogByWeekMap.cs new file mode 100644 index 00000000..48c564c0 --- /dev/null +++ b/samples/Samples.AutoByDate.SqlServer/Domain/Maps/TestLogByWeekMap.cs @@ -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 + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(o => o.Id); + builder.Property(o => o.Id).IsRequired().HasMaxLength(128); + builder.ToTable((nameof(TestLogByWeek))); + } + } +} diff --git a/samples/Samples.AutoByDate.SqlServer/Shardings/TestLogWeekVirtualRoute.cs b/samples/Samples.AutoByDate.SqlServer/Shardings/TestLogWeekVirtualRoute.cs new file mode 100644 index 00000000..6e16f0d0 --- /dev/null +++ b/samples/Samples.AutoByDate.SqlServer/Shardings/TestLogWeekVirtualRoute.cs @@ -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 + { + public override DateTime GetBeginTime() + { + return new DateTime(2021, 8, 1); + } + } +} diff --git a/samples/Samples.AutoByDate.SqlServer/Startup.cs b/samples/Samples.AutoByDate.SqlServer/Startup.cs index 02c15cd4..d828e313 100644 --- a/samples/Samples.AutoByDate.SqlServer/Startup.cs +++ b/samples/Samples.AutoByDate.SqlServer/Startup.cs @@ -43,6 +43,7 @@ namespace Samples.AutoByDate.SqlServer op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection), (conStr,builder) => builder.UseSqlServer(conStr)); op.AddShardingTableRoute(); + op.AddShardingTableRoute(); }); services.AddChronusJob(); } diff --git a/src/ShardingCore/Core/ShardingPage/Abstractions/IShardingPageAccessor.cs b/src/ShardingCore/Core/ShardingPage/Abstractions/IShardingPageAccessor.cs new file mode 100644 index 00000000..d4c86970 --- /dev/null +++ b/src/ShardingCore/Core/ShardingPage/Abstractions/IShardingPageAccessor.cs @@ -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; } + } +} diff --git a/src/ShardingCore/Core/ShardingPage/Abstractions/IShardingPageManager.cs b/src/ShardingCore/Core/ShardingPage/Abstractions/IShardingPageManager.cs new file mode 100644 index 00000000..1b511ec3 --- /dev/null +++ b/src/ShardingCore/Core/ShardingPage/Abstractions/IShardingPageManager.cs @@ -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; } + /// + /// 创建分页scope + /// + /// + ShardingPageScope CreateScope(); + } +} diff --git a/src/ShardingCore/Core/ShardingPage/ShardingPageAccessor.cs b/src/ShardingCore/Core/ShardingPage/ShardingPageAccessor.cs new file mode 100644 index 00000000..dcc7ffeb --- /dev/null +++ b/src/ShardingCore/Core/ShardingPage/ShardingPageAccessor.cs @@ -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 = new AsyncLocal(); + + + /// + public ShardingPageContext ShardingPageContext + { + get => _shardingPageContext.Value; + set => _shardingPageContext.Value = value; + } + } +} diff --git a/src/ShardingCore/Core/ShardingPage/ShardingPageContext.cs b/src/ShardingCore/Core/ShardingPage/ShardingPageContext.cs new file mode 100644 index 00000000..7dd73208 --- /dev/null +++ b/src/ShardingCore/Core/ShardingPage/ShardingPageContext.cs @@ -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> RouteQueryResults { get; } + private ShardingPageContext() + { + RouteQueryResults = new LinkedList>(); + } + public static ShardingPageContext Create() + { + return new ShardingPageContext(); + } + } +} diff --git a/src/ShardingCore/Core/ShardingPage/ShardingPageManager.cs b/src/ShardingCore/Core/ShardingPage/ShardingPageManager.cs new file mode 100644 index 00000000..602e5496 --- /dev/null +++ b/src/ShardingCore/Core/ShardingPage/ShardingPageManager.cs @@ -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; + } + } +} diff --git a/src/ShardingCore/Core/ShardingPage/ShardingPageScope.cs b/src/ShardingCore/Core/ShardingPage/ShardingPageScope.cs new file mode 100644 index 00000000..a743fb26 --- /dev/null +++ b/src/ShardingCore/Core/ShardingPage/ShardingPageScope.cs @@ -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 + { + + /// + /// 分表配置访问器 + /// + public IShardingPageAccessor ShardingPageAccessor { get; } + + /// + /// 构造函数 + /// + /// + public ShardingPageScope(IShardingPageAccessor shardingPageAccessor) + { + ShardingPageAccessor = shardingPageAccessor; + } + + /// + /// 回收 + /// + public void Dispose() + { + ShardingPageAccessor.ShardingPageContext = null; + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs index ace2b114..b0b3de47 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs @@ -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 : IVirtualTableRoute where T : class, IShardingTable { + public virtual IPaginationConfiguration CreatePaginationConfiguration() + { + return null; + } + public Type ShardingEntityType => typeof(T); /// /// 如何将分表字段转成对应的类型 diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/IVirtualTableRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/IVirtualTableRoute.cs index cff7f431..372e491d 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/IVirtualTableRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/IVirtualTableRoute.cs @@ -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 : IVirtualTableRoute where T : class, IShardingTable { + /// + /// 返回null就是表示不开启分页配置 + /// + /// + IPaginationConfiguration CreatePaginationConfiguration(); } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RouteResult.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RouteResult.cs index c1f56282..72a05968 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RouteResult.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/RouteResult.cs @@ -22,6 +22,23 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine } public ISet 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); + } } } \ No newline at end of file diff --git a/src/ShardingCore/Core/VirtualTables/IVirtualTable.cs b/src/ShardingCore/Core/VirtualTables/IVirtualTable.cs index e1bc6448..2cb27e91 100644 --- a/src/ShardingCore/Core/VirtualTables/IVirtualTable.cs +++ b/src/ShardingCore/Core/VirtualTables/IVirtualTable.cs @@ -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 /// 分表配置 /// ShardingTableConfig ShardingConfig { get; } + /// + /// 分页配置 + /// + PaginationMetadata PaginationMetadata { get; } + /// + /// 是否启用分页配置 + /// + bool EnablePagination => PaginationMetadata != null; /// /// 获取所有的物理表 diff --git a/src/ShardingCore/Core/VirtualTables/OneDbVirtualTable.cs b/src/ShardingCore/Core/VirtualTables/OneDbVirtualTable.cs index 556a33c5..eff6e5fd 100644 --- a/src/ShardingCore/Core/VirtualTables/OneDbVirtualTable.cs +++ b/src/ShardingCore/Core/VirtualTables/OneDbVirtualTable.cs @@ -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 _physicTables = new List(); public OneDbVirtualTable(IVirtualTableRoute virtualTableRoute) { _virtualTableRoute = virtualTableRoute; ShardingConfig = ShardingKeyUtil.Parse(EntityType); + var paginationConfiguration = virtualTableRoute.CreatePaginationConfiguration(); + if (paginationConfiguration != null) + { + PaginationMetadata = new PaginationMetadata(); + var paginationBuilder = new PaginationBuilder(PaginationMetadata); + paginationConfiguration.Configure(paginationBuilder); + } } public List GetAllPhysicTables() diff --git a/src/ShardingCore/DIExtension.cs b/src/ShardingCore/DIExtension.cs index 013cbfcc..2fb7dbb0 100644 --- a/src/ShardingCore/DIExtension.cs +++ b/src/ShardingCore/DIExtension.cs @@ -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(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + + //route manage services.AddSingleton(); services.AddSingleton(); + + //sharding page + services.AddSingleton(); + services.AddSingleton(); return services; } diff --git a/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs b/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs index 9478f2fb..22095b55 100644 --- a/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs +++ b/src/ShardingCore/DefaultShardingDbContextCreatorConfig.cs @@ -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 { diff --git a/src/ShardingCore/EFCores/ShardingQueryCompiler.cs b/src/ShardingCore/EFCores/ShardingQueryCompiler.cs index 912f1658..5decac82 100644 --- a/src/ShardingCore/EFCores/ShardingQueryCompiler.cs +++ b/src/ShardingCore/EFCores/ShardingQueryCompiler.cs @@ -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(); + _shardingQueryExecutor = ShardingContainer.GetService(); } - private ICurrentDbContext GetCurrentDbContext() - { - return _currentContext; - } - private TResult EnumerableExecute(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(Expression query) { - var async = false; - var currentDbContext = GetCurrentDbContext().Context; - - if (currentDbContext is IShardingDbContext shardingDbContext) - { - //如果根表达式为iqueryable表示需要迭代 - if (query.Type.HasImplementedRawGeneric(typeof(IQueryable<>))) - { - return EnumerableExecute(shardingDbContext, query, async); - } - - if (query is MethodCallExpression methodCallExpression) - { - switch (methodCallExpression.Method.Name) - { - - case nameof(Enumerable.First): - return GenericMergeExecute(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.FirstOrDefault): - return GenericMergeExecute(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Last): - return GenericMergeExecute(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.LastOrDefault): - return GenericMergeExecute(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Single): - return GenericMergeExecute(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.SingleOrDefault): - return GenericMergeExecute(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Count): - return EnsureMergeExecute(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.LongCount): - return EnsureMergeExecute(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Any): - return EnsureMergeExecute(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.All): - return EnsureMergeExecute(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Max): - return GenericMergeExecute2(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Min): - return GenericMergeExecute2(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Sum): - return EnsureMergeExecute2(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Average): - return EnsureMergeExecute2(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default); - case nameof(Enumerable.Contains): - return EnsureMergeExecute(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 queryable = new EnumerableQuery(expression); - //var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext); - - //var streamMergeEngine = AsyncEnumerableStreamMergeEngine.Create(streamMergeContext); - //return streamMergeEngine.GetAsyncEnumerator(); - } - - throw new ShardingCoreException("db context operator is not IShardingDbContext"); + return _shardingQueryExecutor.Execute(_currentContext, query); } #if !EFCORE2 public TResult ExecuteAsync(Expression query, CancellationToken cancellationToken) { - var currentDbContext = GetCurrentDbContext().Context; - var async = true; - - if (currentDbContext is IShardingDbContext shardingDbContext) - { - if (typeof(TResult).HasImplementedRawGeneric(typeof(IAsyncEnumerable<>))) - { - - return EnumerableExecute(shardingDbContext, query, async); - - } - - if (typeof(TResult).HasImplementedRawGeneric(typeof(Task<>))) - { - if (query is MethodCallExpression methodCallExpression) - { - switch (methodCallExpression.Method.Name) - { - - case nameof(Enumerable.First): - return GenericMergeExecute(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.FirstOrDefault): - return GenericMergeExecute(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Last): - return GenericMergeExecute(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.LastOrDefault): - return GenericMergeExecute(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Single): - return GenericMergeExecute(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.SingleOrDefault): - return GenericMergeExecute(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Count): - return EnsureMergeExecute(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.LongCount): - return EnsureMergeExecute(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Any): - return EnsureMergeExecute(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.All): - return EnsureMergeExecute(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Max): - return GenericMergeExecute2(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Min): - return GenericMergeExecute2(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Sum): - return EnsureMergeExecute2(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Average): - return EnsureMergeExecute2(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Contains): - return EnsureMergeExecute(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - } - } - - } - - - throw new ShardingCoreException($"db context operator not support query expression:[{query.Print()}] result type:[{typeof(TResult).FullName}]"); - //IQueryable queryable = new EnumerableQuery(expression); - //var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext); - - //var streamMergeEngine = AsyncEnumerableStreamMergeEngine.Create(streamMergeContext); - //return streamMergeEngine.GetAsyncEnumerator(); - } - - throw new ShardingCoreException("db context operator is not IShardingDbContext"); + return _shardingQueryExecutor.ExecuteAsync(_currentContext, query, cancellationToken); } public Func CreateCompiledQuery(Expression query) @@ -220,58 +68,6 @@ namespace ShardingCore.EFCores #endif - - private TResult GenericMergeExecute(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(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(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.MergeResultAsync) : nameof(IEnsureMergeResult.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(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.MergeResultAsync) : nameof(IEnsureMergeResult.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 AsyncEnumerableExecute(IShardingDbContext shardingDbContext, Expression query) @@ -369,78 +165,12 @@ namespace ShardingCore.EFCores public IAsyncEnumerable ExecuteAsync(Expression query) { - var currentDbContext = GetCurrentDbContext().Context; - - if (currentDbContext is IShardingDbContext shardingDbContext) - { - return AsyncEnumerableExecute(shardingDbContext, query); - } - - throw new ShardingCoreException("db context operator is not IShardingDbContext"); + return _shardingQueryExecutor.ExecuteAsync>(_currentContext, query, cancellationToken); } public Task ExecuteAsync(Expression query, CancellationToken cancellationToken) { - var currentDbContext = GetCurrentDbContext().Context; - var async = true; - - if (currentDbContext is IShardingDbContext shardingDbContext) - { - if (typeof(TResult).HasImplementedRawGeneric(typeof(IAsyncEnumerable<>))) - { - - return EnumerableExecuteAsync(shardingDbContext, query, async); - - } - - if (query is MethodCallExpression methodCallExpression) - { - switch (methodCallExpression.Method.Name) - { - - case nameof(Enumerable.First): - return GenericMergeExecuteAsync(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.FirstOrDefault): - return GenericMergeExecuteAsync(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Last): - return GenericMergeExecuteAsync(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.LastOrDefault): - return GenericMergeExecuteAsync(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Single): - return GenericMergeExecuteAsync(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.SingleOrDefault): - return GenericMergeExecuteAsync(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Count): - return EnsureMergeExecuteAsync(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.LongCount): - return EnsureMergeExecuteAsync(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Any): - return EnsureMergeExecuteAsync(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.All): - return EnsureMergeExecuteAsync(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Max): - return GenericMergeExecuteAsync2(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Min): - return GenericMergeExecuteAsync2(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); - case nameof(Enumerable.Sum): - return EnsureMergeExecuteAsync2(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, cancellationToken); - case nameof(Enumerable.Average): - return EnsureMergeExecuteAsync2(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression,cancellationToken); - case nameof(Enumerable.Contains): - return EnsureMergeExecuteAsync(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); - } - } - - - throw new ShardingCoreException($"db context operator not support query expression:[{query}] result type:[{typeof(TResult).FullName}]"); - //IQueryable queryable = new EnumerableQuery(expression); - //var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext); - - //var streamMergeEngine = AsyncEnumerableStreamMergeEngine.Create(streamMergeContext); - //return streamMergeEngine.GetAsyncEnumerator(); - } - - throw new ShardingCoreException("db context operator is not IShardingDbContext"); + return _shardingQueryExecutor.ExecuteAsync>(_currentContext, query, cancellationToken); } public Func CreateCompiledQuery(Expression query) diff --git a/src/ShardingCore/Extensions/IShardingQueryableExtension.cs b/src/ShardingCore/Extensions/IShardingQueryableExtension.cs index a7d9976b..368fd178 100644 --- a/src/ShardingCore/Extensions/IShardingQueryableExtension.cs +++ b/src/ShardingCore/Extensions/IShardingQueryableExtension.cs @@ -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 /// internal static IQueryable RemoveSkip(this IQueryable source) { - return (IQueryable)source.Provider.CreateQuery(new RemoveSkipVisitor().Visit(source.Expression)); + var expression = new RemoveSkipVisitor().Visit(source.Expression); + return (IQueryable)source.Provider.CreateQuery(expression); } /// @@ -43,6 +45,17 @@ namespace ShardingCore.Extensions var expression = new RemoveTakeVisitor().Visit(source.Expression); return (IQueryable) source.Provider.CreateQuery(expression); } + internal static IQueryable RemoveOrderBy(this IQueryable source) + { + var expression = new RemoveOrderByVisitor().Visit(source.Expression); + return (IQueryable) source.Provider.CreateQuery(expression); + } + + internal static IQueryable RemoveOrderByDescending(this IQueryable source) + { + var expression = new RemoveOrderByDescendingVisitor().Visit(source.Expression); + return (IQueryable) source.Provider.CreateQuery(expression); + } /// /// 切换数据源,保留原数据源中的Expression diff --git a/src/ShardingCore/Extensions/InternalExtensions/InternalLinqExtension.cs b/src/ShardingCore/Extensions/InternalExtensions/InternalLinqExtension.cs new file mode 100644 index 00000000..80e087ce --- /dev/null +++ b/src/ShardingCore/Extensions/InternalExtensions/InternalLinqExtension.cs @@ -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 OrderByIf(this IEnumerable source, Func keySelector, bool condition, + IComparer? comparer) + { + return condition ? source.OrderBy(keySelector, comparer) : source; + } + public static IEnumerable OrderByDescendingIf(this IEnumerable source, Func keySelector, bool condition, + IComparer? comparer) + { + return condition ? source.OrderByDescending(keySelector, comparer) : source; + } + } +} diff --git a/src/ShardingCore/Extensions/InternalExtensions/InternalPaginationMetadataExtension.cs b/src/ShardingCore/Extensions/InternalExtensions/InternalPaginationMetadataExtension.cs new file mode 100644 index 00000000..ab7a1da5 --- /dev/null +++ b/src/ShardingCore/Extensions/InternalExtensions/InternalPaginationMetadataExtension.cs @@ -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; + } + } +} diff --git a/src/ShardingCore/Extensions/LinqExtension.cs b/src/ShardingCore/Extensions/LinqExtension.cs index d8301075..d0a5adf1 100644 --- a/src/ShardingCore/Extensions/LinqExtension.cs +++ b/src/ShardingCore/Extensions/LinqExtension.cs @@ -61,6 +61,29 @@ namespace ShardingCore.Extensions func(item); } } - + + /// + /// 是否有差异 + /// + /// + /// + /// + public static bool HasDifference(this IEnumerable source) + { + return source.Distinct().Count() > 1; + } + /// + /// 是否有差异 + /// + /// + /// + /// + /// + /// + public static bool HasDifference(this IEnumerable source, Func keySelector) + { + return source.Select(keySelector).Distinct().Count() > 1; + } + } } \ No newline at end of file diff --git a/src/ShardingCore/Extensions/ObjectExtension.cs b/src/ShardingCore/Extensions/ObjectExtension.cs index b004de26..cdb54801 100644 --- a/src/ShardingCore/Extensions/ObjectExtension.cs +++ b/src/ShardingCore/Extensions/ObjectExtension.cs @@ -72,6 +72,17 @@ namespace ShardingCore.Extensions return null; } } + /// + /// 类型X是否包含某个属性 + /// + /// + /// + /// + public static bool ContainPropertyName(this Type type, string propertyName) + { + var property = type.GetProperty(propertyName, _bindingFlags); + return property != null; + } } } \ No newline at end of file diff --git a/src/ShardingCore/Extensions/ShardingExtension.cs b/src/ShardingCore/Extensions/ShardingExtension.cs index e73e68c6..f20dbb43 100644 --- a/src/ShardingCore/Extensions/ShardingExtension.cs +++ b/src/ShardingCore/Extensions/ShardingExtension.cs @@ -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 } } } diff --git a/src/ShardingCore/Extensions/ShardingQueryableExtension.cs b/src/ShardingCore/Extensions/ShardingQueryableExtension.cs new file mode 100644 index 00000000..46ca5585 --- /dev/null +++ b/src/ShardingCore/Extensions/ShardingQueryableExtension.cs @@ -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> ToShardingPageAsync(this IQueryable 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(); + using (shardingPageManager.CreateScope()) + { + //获取每次总记录数 + var count = await source.LongCountAsync(); + if (count <= skip) + return new ShardingPagedResult(new List(0), count); + var data = await source.Skip(skip).Take(take).ToListAsync(); + return new ShardingPagedResult(data, count); + } + } + public static ShardingPagedResult ToShardingPage(this IQueryable 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(); + using (shardingPageManager.CreateScope()) + { + //获取每次总记录数 + var count = source.Count(); + if (count <= skip) + return new ShardingPagedResult(new List(0), count); + var data = source.Skip(skip).Take(take).ToList(); + return new ShardingPagedResult(data, count); + } + } + } +} diff --git a/src/ShardingCore/Extensions/StreamMergeContextExtension.cs b/src/ShardingCore/Extensions/StreamMergeContextExtension.cs new file mode 100644 index 00000000..19044d5d --- /dev/null +++ b/src/ShardingCore/Extensions/StreamMergeContextExtension.cs @@ -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 + { + /// + /// 本次查询是否涉及到分表 + /// + /// + /// + /// + public static bool IsShardingQuery(this StreamMergeContext streamMergeContext) + { + return streamMergeContext.RouteResults.Count() > 1; + } + public static bool IsSingleShardingTableQuery(this StreamMergeContext streamMergeContext) + { + return streamMergeContext.RouteResults.First().ReplaceTables.Count(o => o.EntityType.IsShardingTable()) == 1; + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Extensions/TaskExtension.cs b/src/ShardingCore/Extensions/TaskExtension.cs new file mode 100644 index 00000000..15aa594e --- /dev/null +++ b/src/ShardingCore/Extensions/TaskExtension.cs @@ -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 + { + /// + /// 是否成功 + /// + /// + /// + public static bool IsCompletedSuccessfully(this Task task) + { + return task.IsCompleted && !(task.IsCanceled || task.IsFaulted); + } + + + + /// + /// Waits for the task to complete, unwrapping any exceptions. + /// + /// The task. May not be null. + public static void WaitAndUnwrapException(this Task task) + { + if (task == null) + throw new ArgumentNullException(nameof(task)); + task.GetAwaiter().GetResult(); + } + + /// + /// Waits for the task to complete, unwrapping any exceptions. + /// + /// The task. May not be null. + /// A cancellation token to observe while waiting for the task to complete. + /// The was cancelled before the completed, or the raised an . + 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; + } + } + + /// + /// Waits for the task to complete, unwrapping any exceptions. + /// + /// The type of the result of the task. + /// The task. May not be null. + /// The result of the task. + public static TResult WaitAndUnwrapException(this Task task) + { + if (task == null) + throw new ArgumentNullException(nameof(task)); + return task.GetAwaiter().GetResult(); + } + + /// + /// Waits for the task to complete, unwrapping any exceptions. + /// + /// The type of the result of the task. + /// The task. May not be null. + /// A cancellation token to observe while waiting for the task to complete. + /// The result of the task. + /// The was cancelled before the completed, or the raised an . + public static TResult WaitAndUnwrapException(this Task 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; + } + } + + /// + /// Waits for the task to complete, but does not raise task exceptions. The task exception (if any) is unobserved. + /// + /// The task. May not be null. + public static void WaitWithoutException(this Task task) + { + if (task == null) + throw new ArgumentNullException(nameof(task)); + try + { + task.Wait(); + } + catch (AggregateException) + { + } + } + + /// + /// Waits for the task to complete, but does not raise task exceptions. The task exception (if any) is unobserved. + /// + /// The task. May not be null. + /// A cancellation token to observe while waiting for the task to complete. + /// The was cancelled before the completed. + 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(); + } + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingQueryExecutor.cs b/src/ShardingCore/Sharding/Abstractions/IShardingQueryExecutor.cs new file mode 100644 index 00000000..47d0e080 --- /dev/null +++ b/src/ShardingCore/Sharding/Abstractions/IShardingQueryExecutor.cs @@ -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 + { + /// + /// ͬ��ִ�л�ȡ��� + /// + /// + /// + /// + /// + TResult Execute(ICurrentDbContext currentContext, Expression query); + /// + /// �첽ִ�л�ȡ��� + /// + /// + /// + /// + /// + /// + TResult ExecuteAsync(ICurrentDbContext currentContext, Expression query, CancellationToken cancellationToken = new CancellationToken()); + } +} \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Abstractions/IStreamMergeContextFactory.cs b/src/ShardingCore/Sharding/Abstractions/IStreamMergeContextFactory.cs index 7d5f3426..4c2db7bb 100644 --- a/src/ShardingCore/Sharding/Abstractions/IStreamMergeContextFactory.cs +++ b/src/ShardingCore/Sharding/Abstractions/IStreamMergeContextFactory.cs @@ -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 Create(IQueryable queryable,IShardingDbContext shardingDbContext); + StreamMergeContext Create(IQueryable queryable, IShardingDbContext shardingDbContext); } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/InMemoryReverseStreamMergeAsyncEnumerator.cs b/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/InMemoryReverseStreamMergeAsyncEnumerator.cs new file mode 100644 index 00000000..db5bd03d --- /dev/null +++ b/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/InMemoryReverseStreamMergeAsyncEnumerator.cs @@ -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:IStreamMergeAsyncEnumerator + { + private readonly IStreamMergeAsyncEnumerator _inMemoryStreamMergeAsyncEnumerator; + private bool _first = true; + private IEnumerator _reverseEnumerator = Enumerable.Empty().GetEnumerator(); + public InMemoryReverseStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator inMemoryStreamMergeAsyncEnumerator) + { + _inMemoryStreamMergeAsyncEnumerator = inMemoryStreamMergeAsyncEnumerator; + } + public async ValueTask DisposeAsync() + { + await _inMemoryStreamMergeAsyncEnumerator.DisposeAsync(); + _reverseEnumerator.Dispose(); + } + + public async ValueTask MoveNextAsync() + { + if (_first) + { + ICollection _reverseCollection = new LinkedList(); + 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; + } +} diff --git a/src/ShardingCore/Sharding/PaginationConfigurations/IPaginationConfiguration.cs b/src/ShardingCore/Sharding/PaginationConfigurations/IPaginationConfiguration.cs new file mode 100644 index 00000000..44f6f56a --- /dev/null +++ b/src/ShardingCore/Sharding/PaginationConfigurations/IPaginationConfiguration.cs @@ -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 where TEntity : class,IShardingTable + { + void Configure(PaginationBuilder builder); + } +} diff --git a/src/ShardingCore/Sharding/PaginationConfigurations/PaginationBuilder.cs b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationBuilder.cs new file mode 100644 index 00000000..74afc8ed --- /dev/null +++ b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationBuilder.cs @@ -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 where TEntity:class,IShardingTable + { + private readonly PaginationMetadata _metadata; + + public PaginationBuilder(PaginationMetadata metadata) + { + _metadata = metadata; + } + /// + /// 分页顺序 + /// + /// + /// + public PaginationOrderPropertyBuilder PaginationSequence(Expression> orderPropertyExpression) + { + return new PaginationOrderPropertyBuilder(orderPropertyExpression, _metadata); + } + /// + /// 配置反向排序 仅支持单排序 当skip>= reverseTotalGe*reverseFactor使用反向排序 + /// + /// + /// + /// + public PaginationBuilder ConfigReverseShardingPage(double reverseFactor=0.5,long reverseTotalGe=10000L) + { + _metadata.ReverseFactor = reverseFactor; + _metadata.ReverseTotalGe = reverseTotalGe; + return this; + } + /// + /// 配置当分表数目小于多少后直接取到内存不在流式处理 + /// + /// + /// + public PaginationBuilder ConfigTakeInMemoryCountIfLe(int count) + { + _metadata.TakeInMemoryCountIfLe = count; + return this; + } + } +} diff --git a/src/ShardingCore/Sharding/PaginationConfigurations/PaginationConfig.cs b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationConfig.cs new file mode 100644 index 00000000..4f20f7ee --- /dev/null +++ b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationConfig.cs @@ -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 tailComparer=null) + { + OrderPropertyExpression = orderPropertyExpression; + OrderPropertyInfo = orderPropertyExpression.GetPropertyAccess(); + PropertyName = OrderPropertyInfo.Name; + PaginationMatchEnum = paginationMatchEnum; + TailComparer = tailComparer ?? Comparer.Default; + } + + public LambdaExpression OrderPropertyExpression { get; set; } + public IComparer TailComparer { get; set; } + public PaginationMatchEnum PaginationMatchEnum { get; set; } + public PropertyInfo OrderPropertyInfo { get; set; } + + /// + /// 如果查询没发现排序就将当前配置追加上去 + /// + public bool AppendIfOrderNone => AppendOrder >= 0; + /// + /// 大于等于0表示需要 + /// + 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); + } + } +} diff --git a/src/ShardingCore/Sharding/PaginationConfigurations/PaginationMatchEnum.cs b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationMatchEnum.cs new file mode 100644 index 00000000..44f614e0 --- /dev/null +++ b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationMatchEnum.cs @@ -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 + { + /// + /// ǵǰ + /// + Owner = 1, + /// + /// ֻҪһͿ + /// + Named = 1 << 1, + /// + /// һƥͿ + /// + PrimaryMatch = 1 << 2 + } +} \ No newline at end of file diff --git a/src/ShardingCore/Sharding/PaginationConfigurations/PaginationMetadata.cs b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationMetadata.cs new file mode 100644 index 00000000..1f9bf7d3 --- /dev/null +++ b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationMetadata.cs @@ -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 + */ + /// + /// 分页配置元数据 + /// + public class PaginationMetadata + { + public ISet PaginationConfigs = new HashSet(); + + /// + /// 反向排序因子 + /// + public double ReverseFactor { get; set; } = -1; + + /// + /// 当条数大于多少条后采用反向排序 + /// + public long ReverseTotalGe { get; set; } = 10000L; + /// + /// 是否已开启反向排序 仅支持单排序 + /// + public bool EnableReverseShardingPage => ReverseFactor > 0 && ReverseFactor < 1 && ReverseTotalGe >= 1000; + /// + /// 分表发现如果少于多少条后直接取到内存 LESS THAN OR EQUAL + /// + public int TakeInMemoryCountIfLe { get; set; } = 100; + + } +} diff --git a/src/ShardingCore/Sharding/PaginationConfigurations/PaginationOrderPropertyBuilder.cs b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationOrderPropertyBuilder.cs new file mode 100644 index 00000000..784fae46 --- /dev/null +++ b/src/ShardingCore/Sharding/PaginationConfigurations/PaginationOrderPropertyBuilder.cs @@ -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); + } + + /// + /// 使用哪个后缀比较 + /// + /// + /// + public PaginationOrderPropertyBuilder UseTailCompare(IComparer tailComparer) + { + + _paginationConfig.TailComparer= tailComparer ?? throw new ArgumentException(nameof(tailComparer)); + return this; + } + /// + /// 使用哪种比较方式 + /// + /// + /// + public PaginationOrderPropertyBuilder UseQueryMatch(PaginationMatchEnum paginationMatchEnum) + { + _paginationConfig.PaginationMatchEnum = paginationMatchEnum; + return this; + } + /// + /// 如果查询没发现排序就将当前配置追加上去 + /// + /// 大于等于0生效,越大优先级越高 + /// + public PaginationOrderPropertyBuilder UseAppendIfOrderNone(int order=0) + { + _paginationConfig.AppendOrder = order; + return this; + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Sharding/ShardingQueryExecutors/DefaultShardingQueryExecutor.cs b/src/ShardingCore/Sharding/ShardingQueryExecutors/DefaultShardingQueryExecutor.cs new file mode 100644 index 00000000..7332a081 --- /dev/null +++ b/src/ShardingCore/Sharding/ShardingQueryExecutors/DefaultShardingQueryExecutor.cs @@ -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(ICurrentDbContext currentContext, Expression query) + { + var currentDbContext = currentContext.Context; + + if (currentDbContext is IShardingDbContext shardingDbContext) + { + //如果根表达式为iqueryable表示需要迭代 + if (query.Type.HasImplementedRawGeneric(typeof(IQueryable<>))) + { + return EnumerableExecute(shardingDbContext, query, false); + } + + return DoExecute(shardingDbContext, query, false, default); + } + + throw new ShardingCoreException("db context operator is not IShardingDbContext"); + } + + public TResult ExecuteAsync(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(shardingDbContext, query, true); + + } + + if (typeof(TResult).HasImplementedRawGeneric(typeof(Task<>))) + { + return DoExecute(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(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(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.FirstOrDefault): + return GenericMergeExecute(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Last): + return GenericMergeExecute(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.LastOrDefault): + return GenericMergeExecute(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Single): + return GenericMergeExecute(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.SingleOrDefault): + return GenericMergeExecute(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Count): + return EnsureMergeExecute(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.LongCount): + return EnsureMergeExecute(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Any): + return EnsureMergeExecute(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.All): + return EnsureMergeExecute(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Max): + return GenericMergeExecute2(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Min): + return GenericMergeExecute2(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Sum): + return EnsureMergeExecute2(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Average): + return EnsureMergeExecute2(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); + case nameof(Enumerable.Contains): + return EnsureMergeExecute(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(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(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(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(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.MergeResultAsync) : nameof(IEnsureMergeResult.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(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.MergeResultAsync) + : nameof(IEnsureMergeResult.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); + } + } +} diff --git a/src/ShardingCore/Sharding/ShardingQueryExecutors/EnumeratorShardingQueryExecutor.cs b/src/ShardingCore/Sharding/ShardingQueryExecutors/EnumeratorShardingQueryExecutor.cs new file mode 100644 index 00000000..46468d6d --- /dev/null +++ b/src/ShardingCore/Sharding/ShardingQueryExecutors/EnumeratorShardingQueryExecutor.cs @@ -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 + { + private readonly StreamMergeContext _streamMergeContext; + private readonly IShardingPageManager _shardingPageManager; + private readonly IVirtualTableManager _virtualTableManager; + + public EnumeratorShardingQueryExecutor(StreamMergeContext streamMergeContext) + { + _streamMergeContext = streamMergeContext; + _shardingPageManager = ShardingContainer.GetService(); + _virtualTableManager = ShardingContainer.GetService(); + } + public IEnumeratorStreamMergeEngine ExecuteAsync(CancellationToken cancellationToken = new CancellationToken()) + { + //操作单表 + if (!_streamMergeContext.IsShardingQuery()) + { + return new SingleQueryEnumeratorAsyncStreamMergeEngine(_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(_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(_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( + _streamMergeContext, primaryOrder, total); + } + } + } + } + } + } + + + return new DefaultShardingEnumeratorAsyncStreamMergeEngine(_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; + } + + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index bfb74209..a3343204 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -31,10 +31,11 @@ namespace ShardingCore.Sharding //public DataSourceRoutingResult RoutingResult { get; } public int? Skip { get;} public int? Take { get; } - public IEnumerable Orders { get;} + public IEnumerable Orders { get; private set; } public SelectContext SelectContext { get;} public GroupByContext GroupByContext { get; } + public IEnumerable RouteResults { get; } public StreamMergeContext(IQueryable 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 source,IEnumerable routeResults, // IShardingParallelDbContextFactory shardingParallelDbContextFactory,IShardingScopeFactory shardingScopeFactory) @@ -66,16 +68,15 @@ namespace ShardingCore.Sharding // GroupByContext = reWriteResult.GroupByContext; // _reWriteSource = reWriteResult.ReWriteQueryable; //} - + public void ReSetOrders(IEnumerable orders) + { + Orders = orders; + } public DbContext CreateDbContext(RouteResult routeResult) { var routeTail = _routeTailFactory.Create(routeResult); return _shardingDbContext.GetDbContext(false, routeTail); } - public IEnumerable 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; + } + } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallConstantInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallConstantInMemoryAsyncMergeEngine.cs index f87a8bf2..49c9dc8d 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallConstantInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallConstantInMemoryAsyncMergeEngine.cs @@ -35,7 +35,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx } _constantItem = (TEntity)constantExpression.Value; } - protected override IQueryable ProcessSecondExpression(IQueryable queryable, Expression secondExpression) + protected override IQueryable CombineQueryable(IQueryable queryable, Expression secondExpression) { if (!(secondExpression is ConstantExpression)) { diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine.cs index c7aa7ca0..bebb75db 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine.cs @@ -21,7 +21,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx { } - public override IQueryable EFQueryAfterFilter(IQueryable queryable) + public override IQueryable DoCombineQueryable(IQueryable queryable) { var secondExpression = GetSecondExpression(); if (secondExpression != null) @@ -41,7 +41,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx return queryable; } - protected override IQueryable ProcessSecondExpression(IQueryable _queryable, Expression secondExpression) + protected override IQueryable CombineQueryable(IQueryable _queryable, Expression secondExpression) { return _queryable; } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine.cs index d984d852..6e79cda4 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractEnsureExpressionMergeEngines/AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine.cs @@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx _methodCallExpression = methodCallExpression; } - protected override IQueryable ProcessSecondExpression(IQueryable queryable, Expression secondExpression) + protected override IQueryable CombineQueryable(IQueryable queryable, Expression secondExpression) { if (secondExpression is UnaryExpression where && where.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression> predicate) { diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine.cs index 703e1e80..2685e904 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine.cs @@ -20,7 +20,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE { } - public override IQueryable EFQueryAfterFilter(IQueryable queryable) + public override IQueryable DoCombineQueryable(IQueryable queryable) { var secondExpression = GetSecondExpression(); if (secondExpression != null) @@ -41,7 +41,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE return queryable; } - protected override IQueryable ProcessSecondExpression(IQueryable _queryable, Expression secondExpression) + protected override IQueryable CombineQueryable(IQueryable _queryable, Expression secondExpression) { return _queryable; } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallWhereInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallWhereInMemoryAsyncMergeEngine.cs index 4d15fdbb..5c88b204 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallWhereInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractGenericExpressionMergeEngines/AbstractGenericMethodCallWhereInMemoryAsyncMergeEngine.cs @@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE _methodCallExpression = methodCallExpression; } - protected override IQueryable ProcessSecondExpression(IQueryable queryable, Expression secondExpression) + protected override IQueryable CombineQueryable(IQueryable queryable, Expression secondExpression) { if (secondExpression is UnaryExpression where) { diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs index 60208e88..931b93b5 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/AbstractInMemoryAsyncMergeEngine.cs @@ -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(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(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().Create(_queryable, shardingDbContext); _parllelDbbContexts = new List(); } - - protected abstract IQueryable ProcessSecondExpression(IQueryable queryable, Expression secondExpression); + /// + /// 合并queryable + /// + /// + /// + /// + protected abstract IQueryable CombineQueryable(IQueryable queryable, Expression secondExpression); private IQueryable CreateAsyncExecuteQueryable(RouteResult routeResult) { @@ -69,13 +74,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions _parllelDbbContexts.Add(shardingDbContext); var newQueryable = (IQueryable) GetStreamMergeContext().GetReWriteQueryable() .ReplaceDbContextQueryable(shardingDbContext); - var newFilterQueryable = EFQueryAfterFilter(newQueryable); - return newFilterQueryable; + var newCombineQueryable= DoCombineQueryable(newQueryable); + return newCombineQueryable +; } - public async Task> ExecuteAsync(Func> efQuery, CancellationToken cancellationToken = new CancellationToken()) + public async Task>> ExecuteAsync(Func> 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(routeResult); - return await efQuery(asyncExecuteQueryable); + var queryResult= await efQuery(asyncExecuteQueryable); + return new RouteQueryResult(routeResult, queryResult); //} } catch (Exception e) @@ -99,7 +106,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions public List Execute(Func 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(IQueryable queryable) + public virtual IQueryable DoCombineQueryable(IQueryable queryable) { return queryable; } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/IInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/IInMemoryAsyncMergeEngine.cs index a1c0721f..29a3b29c 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/IInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/Abstractions/IInMemoryAsyncMergeEngine.cs @@ -17,7 +17,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions public interface IInMemoryAsyncMergeEngine { StreamMergeContext GetStreamMergeContext(); - Task> ExecuteAsync(Func> efQuery, + Task>> ExecuteAsync(Func> efQuery, CancellationToken cancellationToken = new CancellationToken()); } } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs index 07b3b6c5..8f54bbbc 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs @@ -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)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)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)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)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)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)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)queryable).Average() - ); - var average = result.Sum() / result.Count; - return ConvertSum(average); - } - - if (typeof(double?) == typeof(TEnsureResult)) - { - var result = base.Execute( - queryable => ((IQueryable)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)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)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 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)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 number) diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MaxAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MaxAsyncInMemoryMergeEngine.cs index 78777db3..9e004ed5 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MaxAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MaxAsyncInMemoryMergeEngine.cs @@ -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() { - var result = base.Execute( queryable => ((IQueryable)queryable).Max()); - return result.Max(); + return AsyncHelper.RunSync(() => MergeResultAsync()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)queryable).MaxAsync(cancellationToken), cancellationToken); - return result.Max(); + return result.Max(o=>o.QueryResult); } } } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MinAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MinAsyncInMemoryMergeEngine.cs index c89cf849..cfd843fb 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MinAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/MinAsyncInMemoryMergeEngine.cs @@ -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() { - var result = base.Execute( queryable => ((IQueryable)queryable).Min()); - return result.Min(); + + return AsyncHelper.RunSync(() => MergeResultAsync()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)queryable).MinAsync(cancellationToken), cancellationToken); - return result.Min(); + return result.Min(o=>o.QueryResult); } } } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/SumAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/SumAsyncInMemoryMergeEngine.cs index 596ad279..17d0efa6 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/SumAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AggregateMergeEngines/SumAsyncInMemoryMergeEngine.cs @@ -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)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)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)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)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)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)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)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)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)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)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 MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) @@ -127,7 +42,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines var result = await base.ExecuteAsync(queryable => ((IQueryable)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)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)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)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)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)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)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)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)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)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 number) { diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AllAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AllAsyncInMemoryMergeEngine.cs index 20c7c9b2..35ce5b69 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AllAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AllAsyncInMemoryMergeEngine.cs @@ -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)queryable).Any()); - - return result.All(o => o); + return AsyncHelper.RunSync(()=> MergeResultAsync()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) @@ -39,7 +38,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines var result = await base.ExecuteAsync( queryable => ((IQueryable)queryable).AnyAsync(cancellationToken), cancellationToken); - return result.All(o => o); + return result.All(o => o.QueryResult); } } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AnyAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AnyAsyncInMemoryMergeEngine.cs index 7205749e..a5b9a224 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AnyAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AnyAsyncInMemoryMergeEngine.cs @@ -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)queryable).Any()); - - return result.Any(o => o); + return AsyncHelper.RunSync(() => MergeResultAsync()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)queryable).AnyAsync(cancellationToken), cancellationToken); - return result.Any(o => o); + return result.Any(o => o.QueryResult); } } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/AsyncEnumerableStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/AsyncEnumerableStreamMergeEngine.cs index 311a45fe..9e4924a0 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/AsyncEnumerableStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/AsyncEnumerableStreamMergeEngine.cs @@ -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 : IAsyncEnumerable, IEnumerable, IDisposable + public class AsyncEnumerableStreamMergeEngine : IAsyncEnumerable, IEnumerable { private readonly StreamMergeContext _mergeContext; - private readonly ICollection _parllelDbbContexts; public AsyncEnumerableStreamMergeEngine(StreamMergeContext mergeContext) { _mergeContext = mergeContext; - _parllelDbbContexts = new LinkedList(); } @@ -44,7 +43,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines await enumator.MoveNextAsync(); return enumator; } + public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) + { + return new EnumeratorShardingQueryExecutor(_mergeContext).ExecuteAsync(cancellationToken) + .GetAsyncEnumerator(cancellationToken); + } #endif + #if EFCORE2 private async Task> GetAsyncEnumerator(IQueryable newQueryable) { @@ -52,62 +57,12 @@ namespace ShardingCore.Sharding.StreamMergeEngines await enumator.MoveNext(); return enumator; } -#endif -#if !EFCORE2 - - public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) - { - return GetShardingEnumerator(); - } -#endif - -#if EFCORE2 IAsyncEnumerator IAsyncEnumerable.GetEnumerator() { return GetShardingEnumerator(); } #endif - - private IQueryable CreateAsyncExecuteQueryable(RouteResult routeResult,int routeCount) - { - var shardingDbContext = _mergeContext.CreateDbContext(routeResult); - var useOriginal = routeCount>1; - _parllelDbbContexts.Add(shardingDbContext); - var newQueryable = (IQueryable)(useOriginal?_mergeContext.GetReWriteQueryable():_mergeContext.GetOriginalQueryable()) - .ReplaceDbContextQueryable(shardingDbContext); - return newQueryable; - } - - private IAsyncEnumerator 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(asyncEnumerator); - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } - }); - }).ToArray(); - - var streamEnumerators = Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult(); - if (routeCount>1&&_mergeContext.HasSkipTake()) - return new PaginationStreamMergeAsyncEnumerator(_mergeContext, streamEnumerators); - if (_mergeContext.HasGroupQuery()) - return new MultiAggregateOrderStreamMergeAsyncEnumerator(_mergeContext, streamEnumerators); - return new MultiOrderStreamMergeAsyncEnumerator(_mergeContext, streamEnumerators); - } + private IEnumerator GetEnumerator(IQueryable newQueryable) @@ -119,33 +74,9 @@ namespace ShardingCore.Sharding.StreamMergeEngines public IEnumerator 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(enumerator); - } - catch (Exception e) - { - Console.WriteLine(e); - throw; - } - }); - }).ToArray(); - - var streamEnumerators = Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult(); - if (routeCount > 1 && _mergeContext.HasSkipTake()) - return new PaginationStreamMergeEnumerator(_mergeContext, streamEnumerators); - if (_mergeContext.HasGroupQuery()) - return new MultiAggregateOrderStreamMergeEnumerator(_mergeContext, streamEnumerators); - return new MultiOrderStreamMergeEnumerator(_mergeContext, streamEnumerators); + return new EnumeratorShardingQueryExecutor(_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); - } - }); - } - } } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/ContainsAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/ContainsAsyncInMemoryMergeEngine.cs index ae7fb0ff..2302f388 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/ContainsAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/ContainsAsyncInMemoryMergeEngine.cs @@ -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)queryable).Contains(GetConstantItem())); - - return result.Any(o => o); + return AsyncHelper.RunSync(() => MergeResultAsync()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)queryable).ContainsAsync(GetConstantItem(), cancellationToken), cancellationToken); - return result.Any(o => o); + return result.Any(o => o.QueryResult); } } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/CountAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/CountAsyncInMemoryMergeEngine.cs index e938f766..fb63fde3 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/CountAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/CountAsyncInMemoryMergeEngine.cs @@ -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 : AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine { + private readonly IShardingPageManager _shardingPageManager; public CountAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) { + _shardingPageManager = ShardingContainer.GetService(); } public override int MergeResult() { - var result = base.Execute( queryable => ((IQueryable)queryable).Count()); - - return result.Sum(); + return AsyncHelper.RunSync(() => MergeResultAsync()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)queryable).CountAsync(cancellationToken), cancellationToken); - return result.Sum(); + if (_shardingPageManager.Current != null) + { + foreach (var routeQueryResult in result) + { + _shardingPageManager.Current.RouteQueryResults.Add(new RouteQueryResult(routeQueryResult.RouteResult, routeQueryResult.QueryResult)); + } + } + return result.Sum(o=>o.QueryResult); } } diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorAsyncStreamMergeEngine.cs new file mode 100644 index 00000000..b508e885 --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorAsyncStreamMergeEngine.cs @@ -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: AbstractEnumeratorStreamMergeEngine + { + public AbstractEnumeratorAsyncStreamMergeEngine(StreamMergeContext streamMergeContext) : base(streamMergeContext) + { + } + + public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) + { + var dbStreamMergeAsyncEnumerators = GetDbStreamMergeAsyncEnumerators(); + if (dbStreamMergeAsyncEnumerators.IsEmpty()) + throw new ShardingCoreException("GetDbStreamMergeAsyncEnumerators empty"); + return GetStreamMergeAsyncEnumerator(dbStreamMergeAsyncEnumerators); + } + + public abstract IStreamMergeAsyncEnumerator[] GetDbStreamMergeAsyncEnumerators(); + public abstract IStreamMergeAsyncEnumerator GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator[] streamsAsyncEnumerators); + public async Task> DoGetAsyncEnumerator(IQueryable newQueryable) + { + var enumator = newQueryable.AsAsyncEnumerable().GetAsyncEnumerator(); + await enumator.MoveNextAsync(); + return enumator; + } + // public virtual IQueryable CreateAsyncExecuteQueryable(RouteResult routeResult) + // { + // var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult); + // var useOriginal = StreamMergeContext > 1; + // DbContextQueryStore.TryAdd(routeResult,shardingDbContext); + // var newQueryable = (IQueryable)(useOriginal ? StreamMergeContext.GetReWriteQueryable() : StreamMergeContext.GetOriginalQueryable()) + // .ReplaceDbContextQueryable(shardingDbContext); + // return newQueryable; + // } + + public override IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorStreamMergeEngine.cs new file mode 100644 index 00000000..945474ef --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorStreamMergeEngine.cs @@ -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:IEnumeratorStreamMergeEngine + { + public StreamMergeContext StreamMergeContext { get; } + public ConcurrentDictionary DbContextQueryStore { get; } + + public AbstractEnumeratorStreamMergeEngine(StreamMergeContext streamMergeContext) + { + StreamMergeContext = streamMergeContext; + DbContextQueryStore = new ConcurrentDictionary(); + } + + public abstract IAsyncEnumerator GetAsyncEnumerator( + CancellationToken cancellationToken = new CancellationToken()); + + public abstract IEnumerator GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Dispose() + { + if (DbContextQueryStore.IsNotEmpty()) + { + DbContextQueryStore.Values.ForEach(dbContext => + { + dbContext.Dispose(); + }); + } + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorSyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorSyncStreamMergeEngine.cs new file mode 100644 index 00000000..94270b0e --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/AbstractEnumeratorSyncStreamMergeEngine.cs @@ -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 : AbstractEnumeratorStreamMergeEngine + { + public AbstractEnumeratorSyncStreamMergeEngine(StreamMergeContext streamMergeContext) : base(streamMergeContext) + { + } + + public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) + { + throw new NotImplementedException(); + } + + public override IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/IEnumeratorStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/IEnumeratorStreamMergeEngine.cs new file mode 100644 index 00000000..e454e26f --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Abstractions/IEnumeratorStreamMergeEngine.cs @@ -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 : IAsyncEnumerable, IEnumerable, IDisposable + { + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/AppenOrderSequenceEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/AppenOrderSequenceEnumeratorAsyncStreamMergeEngine.cs new file mode 100644 index 00000000..bc587bb0 --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/AppenOrderSequenceEnumeratorAsyncStreamMergeEngine.cs @@ -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 : AbstractEnumeratorAsyncStreamMergeEngine + { + private readonly PaginationConfig _appendPaginationConfig; + private readonly ICollection> _routeQueryResults; + private IShardingPageManager _shardingPageManager; + private IVirtualTableManager _virtualTableManager; + public AppenOrderSequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext streamMergeContext, PaginationConfig appendPaginationConfig, ICollection> routeQueryResults) : base(streamMergeContext) + { + _appendPaginationConfig = appendPaginationConfig; + _routeQueryResults = routeQueryResults; + _shardingPageManager = ShardingContainer.GetService(); + _virtualTableManager = ShardingContainer.GetService(); + } + + public override IStreamMergeAsyncEnumerator[] 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(asyncEnumerator); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + }); + }).ToArray(); + + var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException(); + return streamEnumerators; + } + + private IQueryable CreateAsyncExecuteQueryable(IQueryable noPaginationQueryable, SequenceResult sequenceResult) + { + var shardingDbContext = StreamMergeContext.CreateDbContext(sequenceResult.RouteResult); + DbContextQueryStore.TryAdd(sequenceResult.RouteResult, shardingDbContext); + var newQueryable = (IQueryable)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take).OrderWithExpression(new PropertyOrder[]{new PropertyOrder(_appendPaginationConfig.PropertyName,true)})) + .ReplaceDbContextQueryable(shardingDbContext); + return newQueryable; + } + + public override IStreamMergeAsyncEnumerator GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator[] streamsAsyncEnumerators) + { + if (StreamMergeContext.HasGroupQuery()) + return new MultiAggregateOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + return new MultiOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Base/SequencePaginationList.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Base/SequencePaginationList.cs new file mode 100644 index 00000000..61ade0b0 --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/Base/SequencePaginationList.cs @@ -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> _routeQueryResults; + private long? _skip; + private long? _take; + + public SequencePaginationList(IEnumerable> routeQueryResults) + { + _routeQueryResults = routeQueryResults; + } + public SequencePaginationList Skip(long? skip) + { + _skip = skip; + return this; + } + public SequencePaginationList Take(long? take) + { + _take = take; + return this; + } + + public ICollection ToList() + { + ICollection routeResults = new LinkedList(); + + 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; } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs new file mode 100644 index 00000000..7696322a --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs @@ -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:AbstractEnumeratorAsyncStreamMergeEngine + { + public DefaultShardingEnumeratorAsyncStreamMergeEngine(StreamMergeContext streamMergeContext) : base(streamMergeContext) + { + } + + public override IStreamMergeAsyncEnumerator[] 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(asyncEnumerator); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + }); + }).ToArray(); + + var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException(); + return streamEnumerators; + } + + private IQueryable CreateAsyncExecuteQueryable(RouteResult routeResult) + { + var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult); + DbContextQueryStore.TryAdd(routeResult, shardingDbContext); + var newQueryable = (IQueryable)StreamMergeContext.GetReWriteQueryable() + .ReplaceDbContextQueryable(shardingDbContext); + return newQueryable; + } + + public override IStreamMergeAsyncEnumerator GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator[] streamsAsyncEnumerators) + { + if (StreamMergeContext.IsPaginationQuery()) + return new PaginationStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + if (StreamMergeContext.HasGroupQuery()) + return new MultiAggregateOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + return new MultiOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs new file mode 100644 index 00000000..bb5ae50f --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs @@ -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 : AbstractEnumeratorAsyncStreamMergeEngine + { + private readonly PropertyOrder _primaryOrder; + private readonly long _total; + + public ReverseShardingEnumeratorAsyncStreamMergeEngine(StreamMergeContext streamMergeContext, PropertyOrder primaryOrder, long total) : base(streamMergeContext) + { + _primaryOrder = primaryOrder; + _total = total; + } + + public override IStreamMergeAsyncEnumerator[] 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() + { + 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(asyncEnumerator); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + }); + }).ToArray(); + + var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException(); + return streamEnumerators; + } + + private IQueryable CreateAsyncExecuteQueryable(IQueryable reverseOrderQueryable, RouteResult routeResult) + { + var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult); + DbContextQueryStore.TryAdd(routeResult, shardingDbContext); + var newQueryable = (IQueryable)reverseOrderQueryable + .ReplaceDbContextQueryable(shardingDbContext); + return newQueryable; + } + + public override IStreamMergeAsyncEnumerator GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator[] streamsAsyncEnumerators) + { + var doGetStreamMergeAsyncEnumerator = DoGetStreamMergeAsyncEnumerator(streamsAsyncEnumerators); + return new InMemoryReverseStreamMergeAsyncEnumerator(doGetStreamMergeAsyncEnumerator); + } + + private IStreamMergeAsyncEnumerator DoGetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator[] streamsAsyncEnumerators) + { + if (StreamMergeContext.IsPaginationQuery()) + return new PaginationStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + if (StreamMergeContext.HasGroupQuery()) + return new MultiAggregateOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + return new MultiOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/SequenceEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/SequenceEnumeratorAsyncStreamMergeEngine.cs new file mode 100644 index 00000000..cc3d3f60 --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/SequenceEnumeratorAsyncStreamMergeEngine.cs @@ -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 : AbstractEnumeratorAsyncStreamMergeEngine + { + private readonly PaginationConfig _orderPaginationConfig; + private readonly ICollection> _routeQueryResults; + private readonly bool _isAsc; + public SequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext streamMergeContext, PaginationConfig orderPaginationConfig, ICollection> routeQueryResults, bool isAsc) : base(streamMergeContext) + { + _orderPaginationConfig = orderPaginationConfig; + _routeQueryResults = routeQueryResults; + _isAsc = isAsc; + } + + public override IStreamMergeAsyncEnumerator[] 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(asyncEnumerator); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + }); + }).ToArray(); + + var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException(); + return streamEnumerators; + } + + private IQueryable CreateAsyncExecuteQueryable(IQueryable noPaginationQueryable, SequenceResult sequenceResult) + { + var shardingDbContext = StreamMergeContext.CreateDbContext(sequenceResult.RouteResult); + DbContextQueryStore.TryAdd(sequenceResult.RouteResult, shardingDbContext); + var newQueryable = (IQueryable)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take)) + .ReplaceDbContextQueryable(shardingDbContext); + return newQueryable; + } + + public override IStreamMergeAsyncEnumerator GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator[] streamsAsyncEnumerators) + { + if (StreamMergeContext.HasGroupQuery()) + return new MultiAggregateOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + return new MultiOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/SingleQueryEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/SingleQueryEnumeratorAsyncStreamMergeEngine.cs new file mode 100644 index 00000000..7a5b3aa8 --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/EnumeratorStreamMergeEngines/SingleQueryEnumeratorAsyncStreamMergeEngine.cs @@ -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 : AbstractEnumeratorAsyncStreamMergeEngine + { + public SingleQueryEnumeratorAsyncStreamMergeEngine(StreamMergeContext streamMergeContext) : base(streamMergeContext) + { + } + + public override IStreamMergeAsyncEnumerator[] GetDbStreamMergeAsyncEnumerators() + { + var routeResult = StreamMergeContext.RouteResults.First(); + var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult); + DbContextQueryStore.TryAdd(routeResult, shardingDbContext); + var newQueryable = (IQueryable) StreamMergeContext.GetOriginalQueryable().ReplaceDbContextQueryable(shardingDbContext); + + var asyncEnumerator = DoGetAsyncEnumerator(newQueryable).WaitAndUnwrapException(); + return new[] {new StreamMergeAsyncEnumerator(asyncEnumerator)}; + } + + + public override IStreamMergeAsyncEnumerator GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator[] streamsAsyncEnumerators) + { + return new MultiOrderStreamMergeAsyncEnumerator(StreamMergeContext, streamsAsyncEnumerators); + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/FirstAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/FirstAsyncInMemoryMergeEngine.cs index a7ecadaa..58c1fe07 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/FirstAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/FirstAsyncInMemoryMergeEngine.cs @@ -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() { - var result = base.Execute(queryable => ((IQueryable)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()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)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()) diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/FirstOrDefaultAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/FirstOrDefaultAsyncInMemoryMergeEngine.cs index a2f7947b..0908796f 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/FirstOrDefaultAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/FirstOrDefaultAsyncInMemoryMergeEngine.cs @@ -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() { - var result = base.Execute( queryable => ((IQueryable)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()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)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()) diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/LastAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/LastAsyncInMemoryMergeEngine.cs index e0b6e6be..5dc604d1 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/LastAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/LastAsyncInMemoryMergeEngine.cs @@ -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() { - var result = base.Execute( queryable => ((IQueryable)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()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)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()) diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/LastOrDefaultAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/LastOrDefaultAsyncInMemoryMergeEngine.cs index 97dcf284..e4daaa00 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/LastOrDefaultAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/LastOrDefaultAsyncInMemoryMergeEngine.cs @@ -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() { - var result = base.Execute( queryable => ((IQueryable)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()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)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()) diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/LongCountAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/LongCountAsyncInMemoryMergeEngine.cs index f6c1f5a0..a02cbe5d 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/LongCountAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/LongCountAsyncInMemoryMergeEngine.cs @@ -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 : AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine { + private readonly IShardingPageManager _shardingPageManager; public LongCountAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) { + _shardingPageManager= ShardingContainer.GetService(); } public override long MergeResult() { - - var result = base.Execute( queryable => ((IQueryable)queryable).LongCount()); - - return result.Sum(); + return AsyncHelper.RunSync(() => MergeResultAsync()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) @@ -41,7 +42,15 @@ namespace ShardingCore.Sharding.StreamMergeEngines var result = await base.ExecuteAsync( queryable => ((IQueryable)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); } } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/RouteQueryResult.cs b/src/ShardingCore/Sharding/StreamMergeEngines/RouteQueryResult.cs new file mode 100644 index 00000000..a00b347c --- /dev/null +++ b/src/ShardingCore/Sharding/StreamMergeEngines/RouteQueryResult.cs @@ -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 + { + public RouteResult RouteResult { get; } + public TResult QueryResult { get; } + + public RouteQueryResult(RouteResult routeResult,TResult queryResult) + { + RouteResult = routeResult; + QueryResult = queryResult; + } + } +} diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/SingleAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/SingleAsyncInMemoryMergeEngine.cs index 40251fb1..31671927 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/SingleAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/SingleAsyncInMemoryMergeEngine.cs @@ -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() { - var result = base.Execute( queryable => ((IQueryable)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()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)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()) diff --git a/src/ShardingCore/Sharding/StreamMergeEngines/SingleOrDefaultAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/StreamMergeEngines/SingleOrDefaultAsyncInMemoryMergeEngine.cs index 88c19251..f952b80c 100644 --- a/src/ShardingCore/Sharding/StreamMergeEngines/SingleOrDefaultAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/StreamMergeEngines/SingleOrDefaultAsyncInMemoryMergeEngine.cs @@ -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() { - var result = base.Execute(queryable => ((IQueryable)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()); } public override async Task MergeResultAsync(CancellationToken cancellationToken = new CancellationToken()) { var result = await base.ExecuteAsync( queryable => ((IQueryable)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()) diff --git a/src/ShardingCore/Sharding/Visitors/PropertyOrder.cs b/src/ShardingCore/Sharding/Visitors/PropertyOrder.cs index a4f7be64..cd6c0466 100644 --- a/src/ShardingCore/Sharding/Visitors/PropertyOrder.cs +++ b/src/ShardingCore/Sharding/Visitors/PropertyOrder.cs @@ -1,3 +1,5 @@ +using System; + namespace ShardingCore.Core.Internal.Visitors { /* diff --git a/src/ShardingCore/Sharding/Visitors/QuerySelectDiscoverVisitor.cs b/src/ShardingCore/Sharding/Visitors/QuerySelectDiscoverVisitor.cs index 98bbbbb5..c2049b77 100644 --- a/src/ShardingCore/Sharding/Visitors/QuerySelectDiscoverVisitor.cs +++ b/src/ShardingCore/Sharding/Visitors/QuerySelectDiscoverVisitor.cs @@ -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); } diff --git a/src/ShardingCore/Sharding/Visitors/RemoveOrderByDescendingVisitor.cs b/src/ShardingCore/Sharding/Visitors/RemoveOrderByDescendingVisitor.cs new file mode 100644 index 00000000..13ebf3a1 --- /dev/null +++ b/src/ShardingCore/Sharding/Visitors/RemoveOrderByDescendingVisitor.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Visitors/RemoveOrderByVisitor.cs b/src/ShardingCore/Sharding/Visitors/RemoveOrderByVisitor.cs new file mode 100644 index 00000000..dce3164f --- /dev/null +++ b/src/ShardingCore/Sharding/Visitors/RemoveOrderByVisitor.cs @@ -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); + } + } +} \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Visitors/Selects/SelectProperty.cs b/src/ShardingCore/Sharding/Visitors/Selects/SelectProperty.cs index 2961a1ea..aeff5828 100644 --- a/src/ShardingCore/Sharding/Visitors/Selects/SelectProperty.cs +++ b/src/ShardingCore/Sharding/Visitors/Selects/SelectProperty.cs @@ -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; } diff --git a/src/ShardingCore/ShardingPagedResult.cs b/src/ShardingCore/ShardingPagedResult.cs index f56c8360..484dd632 100644 --- a/src/ShardingCore/ShardingPagedResult.cs +++ b/src/ShardingCore/ShardingPagedResult.cs @@ -15,7 +15,7 @@ namespace ShardingCore /// /// 总记录数。 /// 当前页面的数据。 - public ShardingPagedResult(List data, int total) + public ShardingPagedResult(List data, long total) { this.Total = total; this.Data = data; @@ -26,7 +26,7 @@ namespace ShardingCore /// /// 获取或设置总记录数。 /// - public int Total { get; set; } + public long Total { get; set; } /// /// 分页数据 ///