Merge branch 'smart-sharding-page' into main
This commit is contained in:
commit
f322eaa0b3
|
@ -58,15 +58,15 @@ namespace Sample.SqlServer.Controllers
|
|||
|
||||
|
||||
|
||||
var sresultx11231 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Age == 198198).Select(o => o.Id).Contains("1981");
|
||||
var sresultx1121 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Sum(o => o.Age);
|
||||
var sresultx111 = _defaultTableDbContext.Set<SysUserMod>().FirstOrDefault(o => o.Id == "198");
|
||||
var sresultx2 = _defaultTableDbContext.Set<SysUserMod>().Count(o => o.Age <= 10);
|
||||
var sresultx = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").FirstOrDefault();
|
||||
var sresultx33 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).FirstOrDefault();
|
||||
var sresultxc = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).ToList();
|
||||
var sresultxasdc = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").ToList();
|
||||
var sresult = _defaultTableDbContext.Set<SysUserMod>().ToList();
|
||||
//var sresultx11231 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Age == 198198).Select(o => o.Id).Contains("1981");
|
||||
//var sresultx1121 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Sum(o => o.Age);
|
||||
//var sresultx111 = _defaultTableDbContext.Set<SysUserMod>().FirstOrDefault(o => o.Id == "198");
|
||||
//var sresultx2 = _defaultTableDbContext.Set<SysUserMod>().Count(o => o.Age <= 10);
|
||||
//var sresultx = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").FirstOrDefault();
|
||||
//var sresultx33 = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).FirstOrDefault();
|
||||
//var sresultxc = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).ToList();
|
||||
//var sresultxasdc = _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").ToList();
|
||||
//var sresult = _defaultTableDbContext.Set<SysUserMod>().ToList();
|
||||
|
||||
var sysUserMod98 = result.FirstOrDefault(o => o.Id == "98");
|
||||
_defaultTableDbContext.Attach(sysUserMod98);
|
||||
|
@ -86,5 +86,11 @@ namespace Sample.SqlServer.Controllers
|
|||
}
|
||||
return Ok();
|
||||
}
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Get1([FromQuery] int p,[FromQuery]int s)
|
||||
{
|
||||
var shardingPageResultAsync = await _defaultTableDbContext.Set<SysUserSalary>().OrderByDescending(o=>o.DateOfMonth).ToShardingPageAsync(p, s);
|
||||
return Ok(shardingPageResultAsync);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Sample.SqlServer.DbContexts;
|
||||
using Sample.SqlServer.Domain.Entities;
|
||||
|
@ -25,14 +27,17 @@ namespace Sample.SqlServer
|
|||
|
||||
public static void DbSeed(this IApplicationBuilder app)
|
||||
{
|
||||
using (var scope=app.ApplicationServices.CreateScope())
|
||||
using (var scope = app.ApplicationServices.CreateScope())
|
||||
{
|
||||
var virtualDbContext =scope.ServiceProvider.GetService<DefaultShardingDbContext>();
|
||||
var virtualDbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();
|
||||
if (!virtualDbContext.Set<SysUserMod>().Any())
|
||||
{
|
||||
var ids = Enumerable.Range(1, 1000);
|
||||
var userMods = new List<SysUserMod>();
|
||||
var userSalaries = new List<SysUserSalary>();
|
||||
var SysTests = new List<SysTest>();
|
||||
var beginTime = new DateTime(2020, 1, 1);
|
||||
var endTime = new DateTime(2021, 12, 1);
|
||||
foreach (var id in ids)
|
||||
{
|
||||
userMods.Add(new SysUserMod()
|
||||
|
@ -40,16 +45,38 @@ namespace Sample.SqlServer
|
|||
Id = id.ToString(),
|
||||
Age = id,
|
||||
Name = $"name_{id}",
|
||||
AgeGroup = Math.Abs(id % 10)
|
||||
});
|
||||
SysTests.Add(new SysTest()
|
||||
{
|
||||
Id = id.ToString(),
|
||||
UserId = id.ToString()
|
||||
});
|
||||
var tempTime = beginTime;
|
||||
var i = 0;
|
||||
while (tempTime <= endTime)
|
||||
{
|
||||
var dateOfMonth = $@"{tempTime:yyyyMM}";
|
||||
userSalaries.Add(new SysUserSalary()
|
||||
{
|
||||
Id = $@"{id}{dateOfMonth}",
|
||||
UserId = id.ToString(),
|
||||
DateOfMonth = int.Parse(dateOfMonth),
|
||||
Salary = 700000 + id * 100 * i,
|
||||
SalaryLong = 700000 + id * 100 * i,
|
||||
SalaryDecimal = (700000 + id * 100 * i) / 100m,
|
||||
SalaryDouble = (700000 + id * 100 * i) / 100d,
|
||||
SalaryFloat = (700000 + id * 100 * i) / 100f
|
||||
});
|
||||
tempTime = tempTime.AddMonths(1);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
virtualDbContext.AddRange(userMods);
|
||||
virtualDbContext.AddRange(SysTests);
|
||||
virtualDbContext.AddRange(userSalaries);
|
||||
|
||||
virtualDbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -27,5 +27,6 @@ namespace Sample.SqlServer.Domain.Entities
|
|||
/// 用户姓名
|
||||
/// </summary>
|
||||
public int Age { get; set; }
|
||||
public int AgeGroup { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using ShardingCore.Core;
|
||||
|
||||
namespace Sample.SqlServer.Domain.Entities
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 01 February 2021 15:43:22
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserSalary:IShardingTable
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string UserId { get; set; }
|
||||
/// <summary>
|
||||
/// 每月的金额
|
||||
/// </summary>
|
||||
[ShardingTableKey]
|
||||
public int DateOfMonth { get; set; }
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public int Salary { get; set; }
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public long SalaryLong { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public decimal SalaryDecimal { get; set; }
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public double SalaryDouble { get; set; }
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public float SalaryFloat { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Sample.SqlServer.Domain.Entities;
|
||||
|
||||
namespace Sample.SqlServer.Domain.Maps
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 01 February 2021 15:42:35
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserSalaryMap:IEntityTypeConfiguration<SysUserSalary>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<SysUserSalary> builder)
|
||||
{
|
||||
builder.HasKey(o => o.Id);
|
||||
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
|
||||
builder.Property(o => o.UserId).IsRequired().HasMaxLength(128);
|
||||
builder.ToTable(nameof(SysUserSalary));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Sample.SqlServer.Domain.Entities;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
|
||||
namespace Sample.SqlServer.Shardings
|
||||
{
|
||||
public class SysUserModPaginationConfiguration : IPaginationConfiguration<SysUserMod>
|
||||
{
|
||||
public void Configure(PaginationBuilder<SysUserMod> builder)
|
||||
{
|
||||
builder.PaginationSequence(o => o.Id)
|
||||
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq.Expressions;
|
||||
using Sample.SqlServer.Domain.Entities;
|
||||
using ShardingCore.Core.VirtualRoutes;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
using ShardingCore.VirtualRoutes;
|
||||
using ShardingCore.VirtualRoutes.Mods;
|
||||
|
||||
|
@ -25,5 +26,10 @@ namespace Sample.SqlServer.Shardings
|
|||
public SysUserModVirtualTableRoute() : base(2,3)
|
||||
{
|
||||
}
|
||||
|
||||
public override IPaginationConfiguration<SysUserMod> CreatePaginationConfiguration()
|
||||
{
|
||||
return new SysUserModPaginationConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Sample.SqlServer.Domain.Entities;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
|
||||
namespace Sample.SqlServer.Shardings
|
||||
{
|
||||
public class SysUserSalaryPaginationConfiguration:IPaginationConfiguration<SysUserSalary>
|
||||
{
|
||||
public void Configure(PaginationBuilder<SysUserSalary> builder)
|
||||
{
|
||||
//builder.PaginationSequence(o => o.Id)
|
||||
// .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch);
|
||||
//builder.PaginationSequence(o => o.DateOfMonth)
|
||||
// .UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone();
|
||||
builder.ConfigReverseShardingPage();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sample.SqlServer.Domain.Entities;
|
||||
using ShardingCore.Core.VirtualRoutes;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
|
||||
namespace Sample.SqlServer.Shardings
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 01 February 2021 15:54:55
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute<SysUserSalary,int>
|
||||
{
|
||||
protected override int ConvertToShardingKey(object shardingKey)
|
||||
{
|
||||
return Convert.ToInt32(shardingKey);
|
||||
}
|
||||
|
||||
public override string ShardingKeyToTail(object shardingKey)
|
||||
{
|
||||
var time = ConvertToShardingKey(shardingKey);
|
||||
return TimeFormatToTail(time);
|
||||
}
|
||||
|
||||
|
||||
public override List<string> GetAllTails()
|
||||
{
|
||||
var beginTime = new DateTime(2020, 1, 1);
|
||||
var endTime = new DateTime(2021, 12, 1);
|
||||
var list = new List<string>(24);
|
||||
var tempTime = beginTime;
|
||||
while (tempTime <= endTime)
|
||||
{
|
||||
list.Add($"{tempTime:yyyyMM}");
|
||||
tempTime = tempTime.AddMonths(1);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
protected string TimeFormatToTail(int time)
|
||||
{
|
||||
var dateOfMonth=DateTime.ParseExact($"{time}","yyyyMM",System.Globalization.CultureInfo.InvariantCulture,System.Globalization.DateTimeStyles.AdjustToUniversal);
|
||||
return $"{dateOfMonth:yyyyMM}";
|
||||
}
|
||||
|
||||
protected override Expression<Func<string, bool>> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator)
|
||||
{
|
||||
var t = TimeFormatToTail(shardingKey);
|
||||
switch (shardingOperator)
|
||||
{
|
||||
case ShardingOperatorEnum.GreaterThan:
|
||||
case ShardingOperatorEnum.GreaterThanOrEqual:
|
||||
return tail => String.Compare(tail, t, StringComparison.Ordinal) >= 0;
|
||||
case ShardingOperatorEnum.LessThan:
|
||||
return tail => String.Compare(tail, t, StringComparison.Ordinal) < 0;
|
||||
case ShardingOperatorEnum.LessThanOrEqual:
|
||||
return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0;
|
||||
case ShardingOperatorEnum.Equal: return tail => tail == t;
|
||||
default:
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine($"shardingOperator is not equal scan all table tail");
|
||||
#endif
|
||||
return tail => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IPaginationConfiguration<SysUserSalary> CreatePaginationConfiguration()
|
||||
{
|
||||
return new SysUserSalaryPaginationConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,7 +38,9 @@ namespace Sample.SqlServer
|
|||
//.ReplaceService<IQueryTranslationPostprocessorFactory,SqlServer2008QueryTranslationPostprocessorFactory>()//支持sqlserver2008r2
|
||||
);//使用链接字符串创建dbcontext
|
||||
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
||||
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
|
||||
});
|
||||
|
||||
////不支持MARS不支持追踪的
|
||||
//services.AddShardingDbContext<DefaultShardingDbContext, DefaultTableDbContext>(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx2;Integrated Security=True;")
|
||||
// , op =>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Samples.AutoByDate.SqlServer.Domain.Entities;
|
||||
|
||||
namespace Samples.AutoByDate.SqlServer.Domain.Maps
|
||||
{
|
||||
public class TestLogByWeekMap:IEntityTypeConfiguration<TestLogByWeek>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<TestLogByWeek> builder)
|
||||
{
|
||||
builder.HasKey(o => o.Id);
|
||||
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
|
||||
builder.ToTable((nameof(TestLogByWeek)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Samples.AutoByDate.SqlServer.Domain.Entities;
|
||||
using Samples.AutoByDate.SqlServer.Domain.Maps;
|
||||
using ShardingCore.VirtualRoutes.Weeks;
|
||||
|
||||
namespace Samples.AutoByDate.SqlServer.Shardings
|
||||
{
|
||||
public class TestLogWeekVirtualRoute:AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute<TestLogByWeek>
|
||||
{
|
||||
public override DateTime GetBeginTime()
|
||||
{
|
||||
return new DateTime(2021, 8, 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ namespace Samples.AutoByDate.SqlServer
|
|||
op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection),
|
||||
(conStr,builder) => builder.UseSqlServer(conStr));
|
||||
op.AddShardingTableRoute<SysUserLogByDayVirtualTableRoute>();
|
||||
op.AddShardingTableRoute<TestLogWeekVirtualRoute>();
|
||||
});
|
||||
services.AddChronusJob();
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ShardingCore.Core.ShardingPage.Abstractions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 13:46:37
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public interface IShardingPageManager
|
||||
{
|
||||
ShardingPageContext Current { get; }
|
||||
/// <summary>
|
||||
/// 创建分页scope
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
ShardingPageScope CreateScope();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.ShardingPage
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 13:47:35
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingPageAccessor:IShardingPageAccessor
|
||||
{
|
||||
private static AsyncLocal<ShardingPageContext> _shardingPageContext = new AsyncLocal<ShardingPageContext>();
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public ShardingPageContext ShardingPageContext
|
||||
{
|
||||
get => _shardingPageContext.Value;
|
||||
set => _shardingPageContext.Value = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ShardingCore.Sharding.StreamMergeEngines;
|
||||
|
||||
namespace ShardingCore.Core.ShardingPage
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 13:46:55
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingPageContext
|
||||
{
|
||||
public ICollection<RouteQueryResult<long>> RouteQueryResults { get; }
|
||||
private ShardingPageContext()
|
||||
{
|
||||
RouteQueryResults = new LinkedList<RouteQueryResult<long>>();
|
||||
}
|
||||
public static ShardingPageContext Create()
|
||||
{
|
||||
return new ShardingPageContext();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.ShardingPage
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 13:49:12
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingPageScope : IDisposable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 分表配置访问器
|
||||
/// </summary>
|
||||
public IShardingPageAccessor ShardingPageAccessor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="shardingPageAccessor"></param>
|
||||
public ShardingPageScope(IShardingPageAccessor shardingPageAccessor)
|
||||
{
|
||||
ShardingPageAccessor = shardingPageAccessor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
ShardingPageAccessor.ShardingPageContext = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ using ShardingCore.Core.QueryRouteManagers;
|
|||
using ShardingCore.Core.QueryRouteManagers.Abstractions;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
|
||||
namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
|
||||
{
|
||||
|
@ -17,6 +18,11 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
|
|||
*/
|
||||
public abstract class AbstractVirtualTableRoute<T, TKey> : IVirtualTableRoute<T> where T : class, IShardingTable
|
||||
{
|
||||
public virtual IPaginationConfiguration<T> CreatePaginationConfiguration()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public Type ShardingEntityType => typeof(T);
|
||||
/// <summary>
|
||||
/// 如何将分表字段转成对应的类型
|
||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ShardingCore.Core.PhysicTables;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
|
||||
namespace ShardingCore.Core.VirtualRoutes.TableRoutes
|
||||
{
|
||||
|
@ -44,5 +45,10 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes
|
|||
|
||||
public interface IVirtualTableRoute<T> : IVirtualTableRoute where T : class, IShardingTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回null就是表示不开启分页配置
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IPaginationConfiguration<T> CreatePaginationConfiguration();
|
||||
}
|
||||
}
|
|
@ -22,6 +22,23 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
|
|||
}
|
||||
|
||||
public ISet<IPhysicTable> ReplaceTables { get; }
|
||||
|
||||
|
||||
protected bool Equals(RouteResult other)
|
||||
{
|
||||
return Equals(ReplaceTables, other.ReplaceTables);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((RouteResult) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (ReplaceTables != null ? ReplaceTables.GetHashCode() : 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using ShardingCore.Core.PhysicTables;
|
||||
using ShardingCore.Core.VirtualRoutes;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
|
||||
namespace ShardingCore.Core.VirtualTables
|
||||
{
|
||||
|
@ -22,6 +23,14 @@ namespace ShardingCore.Core.VirtualTables
|
|||
/// 分表配置
|
||||
/// </summary>
|
||||
ShardingTableConfig ShardingConfig { get; }
|
||||
/// <summary>
|
||||
/// 分页配置
|
||||
/// </summary>
|
||||
PaginationMetadata PaginationMetadata { get; }
|
||||
/// <summary>
|
||||
/// 是否启用分页配置
|
||||
/// </summary>
|
||||
bool EnablePagination => PaginationMetadata != null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有的物理表
|
||||
|
|
|
@ -8,6 +8,7 @@ using ShardingCore.Core.VirtualRoutes;
|
|||
using ShardingCore.Core.VirtualRoutes.TableRoutes;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
using ShardingCore.Utils;
|
||||
|
||||
namespace ShardingCore.Core.VirtualTables
|
||||
|
@ -28,12 +29,22 @@ namespace ShardingCore.Core.VirtualTables
|
|||
|
||||
public Type EntityType => typeof(T);
|
||||
public ShardingTableConfig ShardingConfig { get; }
|
||||
|
||||
public PaginationMetadata PaginationMetadata { get; }
|
||||
|
||||
private readonly List<IPhysicTable> _physicTables = new List<IPhysicTable>();
|
||||
|
||||
public OneDbVirtualTable(IVirtualTableRoute<T> virtualTableRoute)
|
||||
{
|
||||
_virtualTableRoute = virtualTableRoute;
|
||||
ShardingConfig = ShardingKeyUtil.Parse(EntityType);
|
||||
var paginationConfiguration = virtualTableRoute.CreatePaginationConfiguration();
|
||||
if (paginationConfiguration != null)
|
||||
{
|
||||
PaginationMetadata = new PaginationMetadata();
|
||||
var paginationBuilder = new PaginationBuilder<T>(PaginationMetadata);
|
||||
paginationConfiguration.Configure(paginationBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
public List<IPhysicTable> GetAllPhysicTables()
|
||||
|
|
|
@ -16,8 +16,11 @@ using ShardingCore.Core.QueryRouteManagers;
|
|||
using ShardingCore.Core.QueryRouteManagers.Abstractions;
|
||||
using ShardingCore.Core.ShardingAccessors;
|
||||
using ShardingCore.Core.ShardingAccessors.Abstractions;
|
||||
using ShardingCore.Core.ShardingPage;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
using ShardingCore.Core.VirtualRoutes;
|
||||
using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingQueryExecutors;
|
||||
|
||||
namespace ShardingCore
|
||||
{
|
||||
|
@ -86,8 +89,15 @@ namespace ShardingCore
|
|||
services.AddSingleton<IShardingAccessor, ShardingAccessor>();
|
||||
services.AddSingleton<IShardingScopeFactory, ShardingScopeFactory>();
|
||||
services.AddSingleton<IRouteTailFactory, RouteTailFactory>();
|
||||
services.AddSingleton<IShardingQueryExecutor, DefaultShardingQueryExecutor>();
|
||||
|
||||
//route manage
|
||||
services.AddSingleton<IShardingRouteManager, ShardingRouteManager>();
|
||||
services.AddSingleton<IShardingRouteAccessor, ShardingRouteAccessor>();
|
||||
|
||||
//sharding page
|
||||
services.AddSingleton<IShardingPageManager, ShardingPageManager>();
|
||||
services.AddSingleton<IShardingPageAccessor, ShardingPageAccessor>();
|
||||
return services;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ using System.Linq;
|
|||
using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
|
||||
#if EFCORE2
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
|
@ -29,178 +30,25 @@ namespace ShardingCore.EFCores
|
|||
public class ShardingQueryCompiler : IQueryCompiler
|
||||
{
|
||||
private readonly ICurrentDbContext _currentContext;
|
||||
private readonly IStreamMergeContextFactory _streamMergeContextFactory;
|
||||
private readonly IShardingQueryExecutor _shardingQueryExecutor;
|
||||
|
||||
public ShardingQueryCompiler(ICurrentDbContext currentContext)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
_streamMergeContextFactory = ShardingContainer.GetService<IStreamMergeContextFactory>();
|
||||
_shardingQueryExecutor = ShardingContainer.GetService<IShardingQueryExecutor>();
|
||||
}
|
||||
|
||||
|
||||
private ICurrentDbContext GetCurrentDbContext()
|
||||
{
|
||||
return _currentContext;
|
||||
}
|
||||
private TResult EnumerableExecute<TResult>(IShardingDbContext shardingDbContext, Expression query, bool async)
|
||||
{
|
||||
Type queryEntityType;
|
||||
if (async)
|
||||
queryEntityType = typeof(TResult).GetGenericArguments()[0];
|
||||
else
|
||||
{
|
||||
queryEntityType = query.Type.GetSequenceType();
|
||||
}
|
||||
Type type = typeof(EnumerableQuery<>);
|
||||
type = type.MakeGenericType(queryEntityType);
|
||||
var queryable = Activator.CreateInstance(type, query);
|
||||
|
||||
var streamMergeContextMethod = _streamMergeContextFactory.GetType().GetMethod("Create");
|
||||
if (streamMergeContextMethod == null)
|
||||
throw new ShardingCoreException("cant found IStreamMergeContextFactory method [Create]");
|
||||
var streamMergeContext = streamMergeContextMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(_streamMergeContextFactory, new[] { queryable, shardingDbContext });
|
||||
|
||||
|
||||
Type streamMergeEngineType = typeof(AsyncEnumerableStreamMergeEngine<>);
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
|
||||
return (TResult)Activator.CreateInstance(streamMergeEngineType, streamMergeContext);
|
||||
}
|
||||
public TResult Execute<TResult>(Expression query)
|
||||
{
|
||||
var async = false;
|
||||
var currentDbContext = GetCurrentDbContext().Context;
|
||||
|
||||
if (currentDbContext is IShardingDbContext shardingDbContext)
|
||||
{
|
||||
//如果根表达式为iqueryable表示需要迭代
|
||||
if (query.Type.HasImplementedRawGeneric(typeof(IQueryable<>)))
|
||||
{
|
||||
return EnumerableExecute<TResult>(shardingDbContext, query, async);
|
||||
}
|
||||
|
||||
if (query is MethodCallExpression methodCallExpression)
|
||||
{
|
||||
switch (methodCallExpression.Method.Name)
|
||||
{
|
||||
|
||||
case nameof(Enumerable.First):
|
||||
return GenericMergeExecute<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.FirstOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Last):
|
||||
return GenericMergeExecute<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.LastOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Single):
|
||||
return GenericMergeExecute<TResult>(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.SingleOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Count):
|
||||
return EnsureMergeExecute<TResult>(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.LongCount):
|
||||
return EnsureMergeExecute<TResult>(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Any):
|
||||
return EnsureMergeExecute<TResult>(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.All):
|
||||
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Max):
|
||||
return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Min):
|
||||
return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Sum):
|
||||
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Average):
|
||||
return EnsureMergeExecute2<TResult>(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
|
||||
case nameof(Enumerable.Contains):
|
||||
return EnsureMergeExecute<TResult>(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !EFCORE2
|
||||
throw new ShardingCoreException($"db context operator not support query expression:[{query.Print()}] result type:[{typeof(TResult).FullName}]");
|
||||
#endif
|
||||
#if EFCORE2
|
||||
throw new ShardingCoreException($"db context operator not support query expression:[{query}] result type:[{typeof(TResult).FullName}]");
|
||||
#endif
|
||||
//IQueryable<TResult> queryable = new EnumerableQuery<TResult>(expression);
|
||||
//var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext);
|
||||
|
||||
//var streamMergeEngine = AsyncEnumerableStreamMergeEngine<TResult>.Create<TResult>(streamMergeContext);
|
||||
//return streamMergeEngine.GetAsyncEnumerator();
|
||||
}
|
||||
|
||||
throw new ShardingCoreException("db context operator is not IShardingDbContext");
|
||||
return _shardingQueryExecutor.Execute<TResult>(_currentContext, query);
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
|
||||
public TResult ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
|
||||
{
|
||||
var currentDbContext = GetCurrentDbContext().Context;
|
||||
var async = true;
|
||||
|
||||
if (currentDbContext is IShardingDbContext shardingDbContext)
|
||||
{
|
||||
if (typeof(TResult).HasImplementedRawGeneric(typeof(IAsyncEnumerable<>)))
|
||||
{
|
||||
|
||||
return EnumerableExecute<TResult>(shardingDbContext, query, async);
|
||||
|
||||
}
|
||||
|
||||
if (typeof(TResult).HasImplementedRawGeneric(typeof(Task<>)))
|
||||
{
|
||||
if (query is MethodCallExpression methodCallExpression)
|
||||
{
|
||||
switch (methodCallExpression.Method.Name)
|
||||
{
|
||||
|
||||
case nameof(Enumerable.First):
|
||||
return GenericMergeExecute<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.FirstOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Last):
|
||||
return GenericMergeExecute<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.LastOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Single):
|
||||
return GenericMergeExecute<TResult>(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.SingleOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Count):
|
||||
return EnsureMergeExecute<TResult>(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.LongCount):
|
||||
return EnsureMergeExecute<TResult>(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Any):
|
||||
return EnsureMergeExecute<TResult>(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.All):
|
||||
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Max):
|
||||
return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Min):
|
||||
return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Sum):
|
||||
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Average):
|
||||
return EnsureMergeExecute2<TResult>(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Contains):
|
||||
return EnsureMergeExecute<TResult>(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
throw new ShardingCoreException($"db context operator not support query expression:[{query.Print()}] result type:[{typeof(TResult).FullName}]");
|
||||
//IQueryable<TResult> queryable = new EnumerableQuery<TResult>(expression);
|
||||
//var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext);
|
||||
|
||||
//var streamMergeEngine = AsyncEnumerableStreamMergeEngine<TResult>.Create<TResult>(streamMergeContext);
|
||||
//return streamMergeEngine.GetAsyncEnumerator();
|
||||
}
|
||||
|
||||
throw new ShardingCoreException("db context operator is not IShardingDbContext");
|
||||
return _shardingQueryExecutor.ExecuteAsync<TResult>(_currentContext, query, cancellationToken);
|
||||
}
|
||||
|
||||
public Func<QueryContext, TResult> CreateCompiledQuery<TResult>(Expression query)
|
||||
|
@ -220,58 +68,6 @@ namespace ShardingCore.EFCores
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
private TResult GenericMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
|
||||
{
|
||||
var queryEntityType = query.GetQueryEntityType();
|
||||
var resultEntityType = query.GetResultType();
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
|
||||
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
|
||||
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
|
||||
if (streamEngineMethod == null)
|
||||
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
|
||||
var @params = async ? new object[] { cancellationToken } : new object[0];
|
||||
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamEngine, @params);
|
||||
}
|
||||
private TResult GenericMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
|
||||
{
|
||||
var queryEntityType = query.GetQueryEntityType();
|
||||
var resultType = query.GetResultType();
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType,resultType);
|
||||
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
|
||||
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
|
||||
if (streamEngineMethod == null)
|
||||
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
|
||||
var @params = async ? new object[] { cancellationToken } : new object[0];
|
||||
//typeof(TResult)==?resultType
|
||||
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params);
|
||||
}
|
||||
|
||||
|
||||
private TResult EnsureMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
|
||||
{
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType());
|
||||
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
|
||||
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IEnsureMergeResult<object>.MergeResultAsync) : nameof(IEnsureMergeResult<object>.MergeResult));
|
||||
if (streamEngineMethod == null)
|
||||
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
|
||||
var @params = async ? new object[] { cancellationToken } : new object[0];
|
||||
return (TResult)streamEngineMethod.Invoke(streamEngine, @params);
|
||||
}
|
||||
|
||||
private TResult EnsureMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
|
||||
{
|
||||
if (async)
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType(), typeof(TResult).GetGenericArguments()[0]);
|
||||
else
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType(), typeof(TResult));
|
||||
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
|
||||
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IEnsureMergeResult<object>.MergeResultAsync) : nameof(IEnsureMergeResult<object>.MergeResult));
|
||||
if (streamEngineMethod == null)
|
||||
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
|
||||
var @params = async ? new object[] { cancellationToken } : new object[0];
|
||||
return (TResult)streamEngineMethod.Invoke(streamEngine, @params);
|
||||
}
|
||||
#if EFCORE2
|
||||
|
||||
private IAsyncEnumerable<TResult> AsyncEnumerableExecute<TResult>(IShardingDbContext shardingDbContext, Expression query)
|
||||
|
@ -369,78 +165,12 @@ namespace ShardingCore.EFCores
|
|||
|
||||
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression query)
|
||||
{
|
||||
var currentDbContext = GetCurrentDbContext().Context;
|
||||
|
||||
if (currentDbContext is IShardingDbContext shardingDbContext)
|
||||
{
|
||||
return AsyncEnumerableExecute<TResult>(shardingDbContext, query);
|
||||
}
|
||||
|
||||
throw new ShardingCoreException("db context operator is not IShardingDbContext");
|
||||
return _shardingQueryExecutor.ExecuteAsync<IAsyncEnumerable<TResult>>(_currentContext, query, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<TResult> ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
|
||||
{
|
||||
var currentDbContext = GetCurrentDbContext().Context;
|
||||
var async = true;
|
||||
|
||||
if (currentDbContext is IShardingDbContext shardingDbContext)
|
||||
{
|
||||
if (typeof(TResult).HasImplementedRawGeneric(typeof(IAsyncEnumerable<>)))
|
||||
{
|
||||
|
||||
return EnumerableExecuteAsync<TResult>(shardingDbContext, query, async);
|
||||
|
||||
}
|
||||
|
||||
if (query is MethodCallExpression methodCallExpression)
|
||||
{
|
||||
switch (methodCallExpression.Method.Name)
|
||||
{
|
||||
|
||||
case nameof(Enumerable.First):
|
||||
return GenericMergeExecuteAsync<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.FirstOrDefault):
|
||||
return GenericMergeExecuteAsync<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Last):
|
||||
return GenericMergeExecuteAsync<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.LastOrDefault):
|
||||
return GenericMergeExecuteAsync<TResult>(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Single):
|
||||
return GenericMergeExecuteAsync<TResult>(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.SingleOrDefault):
|
||||
return GenericMergeExecuteAsync<TResult>(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Count):
|
||||
return EnsureMergeExecuteAsync<TResult>(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.LongCount):
|
||||
return EnsureMergeExecuteAsync<TResult>(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Any):
|
||||
return EnsureMergeExecuteAsync<TResult>(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.All):
|
||||
return EnsureMergeExecuteAsync<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Max):
|
||||
return GenericMergeExecuteAsync2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Min):
|
||||
return GenericMergeExecuteAsync2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Sum):
|
||||
return EnsureMergeExecuteAsync2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, cancellationToken);
|
||||
case nameof(Enumerable.Average):
|
||||
return EnsureMergeExecuteAsync2<TResult>(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression,cancellationToken);
|
||||
case nameof(Enumerable.Contains):
|
||||
return EnsureMergeExecuteAsync<TResult>(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
throw new ShardingCoreException($"db context operator not support query expression:[{query}] result type:[{typeof(TResult).FullName}]");
|
||||
//IQueryable<TResult> queryable = new EnumerableQuery<TResult>(expression);
|
||||
//var streamMergeContext = _streamMergeContextFactory.Create(queryable, shardingDbContext);
|
||||
|
||||
//var streamMergeEngine = AsyncEnumerableStreamMergeEngine<TResult>.Create<TResult>(streamMergeContext);
|
||||
//return streamMergeEngine.GetAsyncEnumerator();
|
||||
}
|
||||
|
||||
throw new ShardingCoreException("db context operator is not IShardingDbContext");
|
||||
return _shardingQueryExecutor.ExecuteAsync<Task<TResult>>(_currentContext, query, cancellationToken);
|
||||
}
|
||||
|
||||
public Func<QueryContext, TResult> CreateCompiledQuery<TResult>(Expression query)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Sharding.Visitors;
|
||||
|
||||
namespace ShardingCore.Extensions
|
||||
{
|
||||
|
@ -29,7 +30,8 @@ namespace ShardingCore.Extensions
|
|||
/// <returns></returns>
|
||||
internal static IQueryable<T> RemoveSkip<T>(this IQueryable<T> source)
|
||||
{
|
||||
return (IQueryable<T>)source.Provider.CreateQuery(new RemoveSkipVisitor().Visit(source.Expression));
|
||||
var expression = new RemoveSkipVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>)source.Provider.CreateQuery(expression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -43,6 +45,17 @@ namespace ShardingCore.Extensions
|
|||
var expression = new RemoveTakeVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>) source.Provider.CreateQuery(expression);
|
||||
}
|
||||
internal static IQueryable<T> RemoveOrderBy<T>(this IQueryable<T> source)
|
||||
{
|
||||
var expression = new RemoveOrderByVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>) source.Provider.CreateQuery(expression);
|
||||
}
|
||||
|
||||
internal static IQueryable<T> RemoveOrderByDescending<T>(this IQueryable<T> source)
|
||||
{
|
||||
var expression = new RemoveOrderByDescendingVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>) source.Provider.CreateQuery(expression);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换数据源,保留原数据源中的Expression
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
||||
namespace ShardingCore.Extensions.InternalExtensions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/3 10:13:07
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
internal static class InternalLinqExtension
|
||||
{
|
||||
public static IEnumerable<TShource> OrderByIf<TShource, TKey>(this IEnumerable<TShource> source, Func<TShource, TKey> keySelector, bool condition,
|
||||
IComparer<TKey>? comparer)
|
||||
{
|
||||
return condition ? source.OrderBy(keySelector, comparer) : source;
|
||||
}
|
||||
public static IEnumerable<TShource> OrderByDescendingIf<TShource, TKey>(this IEnumerable<TShource> source, Func<TShource, TKey> keySelector, bool condition,
|
||||
IComparer<TKey>? comparer)
|
||||
{
|
||||
return condition ? source.OrderByDescending(keySelector, comparer) : source;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -61,6 +61,29 @@ namespace ShardingCore.Extensions
|
|||
func(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否有差异
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasDifference<T>(this IEnumerable<T> source)
|
||||
{
|
||||
return source.Distinct().Count() > 1;
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否有差异
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="keySelector"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasDifference<T,TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector)
|
||||
{
|
||||
return source.Select(keySelector).Distinct().Count() > 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -72,6 +72,17 @@ namespace ShardingCore.Extensions
|
|||
return null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 类型X是否包含某个属性
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="propertyName"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ContainPropertyName(this Type type, string propertyName)
|
||||
{
|
||||
var property = type.GetProperty(propertyName, _bindingFlags);
|
||||
return property != null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
|
||||
namespace ShardingCore.Extensions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/3 10:36:51
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public static class ShardingQueryableExtension
|
||||
{
|
||||
public static async Task<ShardingPagedResult<T>> ToShardingPageAsync<T>(this IQueryable<T> source, int pageIndex, int pageSize)
|
||||
{
|
||||
//设置每次获取多少页
|
||||
var take = pageSize <= 0 ? 1 : pageSize;
|
||||
//设置当前页码最小1
|
||||
var index = pageIndex <= 0 ? 1 : pageIndex;
|
||||
//需要跳过多少页
|
||||
var skip = (index - 1) * take;
|
||||
var shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
|
||||
using (shardingPageManager.CreateScope())
|
||||
{
|
||||
//获取每次总记录数
|
||||
var count = await source.LongCountAsync();
|
||||
if (count <= skip)
|
||||
return new ShardingPagedResult<T>(new List<T>(0), count);
|
||||
var data = await source.Skip(skip).Take(take).ToListAsync();
|
||||
return new ShardingPagedResult<T>(data, count);
|
||||
}
|
||||
}
|
||||
public static ShardingPagedResult<T> ToShardingPage<T>(this IQueryable<T> source, int pageIndex, int pageSize)
|
||||
{
|
||||
//设置每次获取多少页
|
||||
var take = pageSize <= 0 ? 1 : pageSize;
|
||||
//设置当前页码最小1
|
||||
var index = pageIndex <= 0 ? 1 : pageIndex;
|
||||
//需要跳过多少页
|
||||
var skip = (index - 1) * take;
|
||||
|
||||
var shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
|
||||
using (shardingPageManager.CreateScope())
|
||||
{
|
||||
//获取每次总记录数
|
||||
var count = source.Count();
|
||||
if (count <= skip)
|
||||
return new ShardingPagedResult<T>(new List<T>(0), count);
|
||||
var data = source.Skip(skip).Take(take).ToList();
|
||||
return new ShardingPagedResult<T>(data, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using ShardingCore.Sharding;
|
||||
|
||||
namespace ShardingCore.Extensions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Thursday, 02 September 2021 20:46:24
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public static class StreamMergeContextExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 本次查询是否涉及到分表
|
||||
/// </summary>
|
||||
/// <param name="streamMergeContext"></param>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static bool IsShardingQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
|
||||
{
|
||||
return streamMergeContext.RouteResults.Count() > 1;
|
||||
}
|
||||
public static bool IsSingleShardingTableQuery<TEntity>(this StreamMergeContext<TEntity> streamMergeContext)
|
||||
{
|
||||
return streamMergeContext.RouteResults.First().ReplaceTables.Count(o => o.EntityType.IsShardingTable()) == 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Extensions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/1 10:22:00
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
internal static class TaskExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
/// <param name="task"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsCompletedSuccessfully(this Task task)
|
||||
{
|
||||
return task.IsCompleted && !(task.IsCanceled || task.IsFaulted);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the task to complete, unwrapping any exceptions.
|
||||
/// </summary>
|
||||
/// <param name="task">The task. May not be <c>null</c>.</param>
|
||||
public static void WaitAndUnwrapException(this Task task)
|
||||
{
|
||||
if (task == null)
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
task.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the task to complete, unwrapping any exceptions.
|
||||
/// </summary>
|
||||
/// <param name="task">The task. May not be <c>null</c>.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
|
||||
/// <exception cref="OperationCanceledException">The <paramref name="cancellationToken"/> was cancelled before the <paramref name="task"/> completed, or the <paramref name="task"/> raised an <see cref="OperationCanceledException"/>.</exception>
|
||||
public static void WaitAndUnwrapException(this Task task, CancellationToken cancellationToken)
|
||||
{
|
||||
if (task == null)
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
try
|
||||
{
|
||||
task.Wait(cancellationToken);
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(ex).Throw();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the task to complete, unwrapping any exceptions.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the result of the task.</typeparam>
|
||||
/// <param name="task">The task. May not be <c>null</c>.</param>
|
||||
/// <returns>The result of the task.</returns>
|
||||
public static TResult WaitAndUnwrapException<TResult>(this Task<TResult> task)
|
||||
{
|
||||
if (task == null)
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
return task.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the task to complete, unwrapping any exceptions.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the result of the task.</typeparam>
|
||||
/// <param name="task">The task. May not be <c>null</c>.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
|
||||
/// <returns>The result of the task.</returns>
|
||||
/// <exception cref="OperationCanceledException">The <paramref name="cancellationToken"/> was cancelled before the <paramref name="task"/> completed, or the <paramref name="task"/> raised an <see cref="OperationCanceledException"/>.</exception>
|
||||
public static TResult WaitAndUnwrapException<TResult>(this Task<TResult> task, CancellationToken cancellationToken)
|
||||
{
|
||||
if (task == null)
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
try
|
||||
{
|
||||
task.Wait(cancellationToken);
|
||||
return task.Result;
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(ex).Throw();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the task to complete, but does not raise task exceptions. The task exception (if any) is unobserved.
|
||||
/// </summary>
|
||||
/// <param name="task">The task. May not be <c>null</c>.</param>
|
||||
public static void WaitWithoutException(this Task task)
|
||||
{
|
||||
if (task == null)
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
try
|
||||
{
|
||||
task.Wait();
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the task to complete, but does not raise task exceptions. The task exception (if any) is unobserved.
|
||||
/// </summary>
|
||||
/// <param name="task">The task. May not be <c>null</c>.</param>
|
||||
/// <param name="cancellationToken">A cancellation token to observe while waiting for the task to complete.</param>
|
||||
/// <exception cref="OperationCanceledException">The <paramref name="cancellationToken"/> was cancelled before the <paramref name="task"/> completed.</exception>
|
||||
public static void WaitWithoutException(this Task task, CancellationToken cancellationToken)
|
||||
{
|
||||
if (task == null)
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
try
|
||||
{
|
||||
task.Wait(cancellationToken);
|
||||
}
|
||||
catch (AggregateException)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
|
||||
namespace ShardingCore.Sharding.Abstractions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Friday, 27 August 2021 22:49:22
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public interface IShardingQueryExecutor
|
||||
{
|
||||
/// <summary>
|
||||
/// ͬ<><CDAC>ִ<EFBFBD>л<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="currentContext"></param>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
TResult Execute<TResult>(ICurrentDbContext currentContext, Expression query);
|
||||
/// <summary>
|
||||
/// <20>첽ִ<ECB2BD>л<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="currentContext"></param>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
TResult ExecuteAsync<TResult>(ICurrentDbContext currentContext, Expression query, CancellationToken cancellationToken = new CancellationToken());
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace ShardingCore.Sharding.Abstractions
|
||||
{
|
||||
|
@ -10,6 +11,6 @@ namespace ShardingCore.Sharding.Abstractions
|
|||
*/
|
||||
public interface IStreamMergeContextFactory
|
||||
{
|
||||
StreamMergeContext<T> Create<T>(IQueryable<T> queryable,IShardingDbContext shardingDbContext);
|
||||
StreamMergeContext<T> Create<T>(IQueryable<T> queryable, IShardingDbContext shardingDbContext);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/3 15:30:32
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class InMemoryReverseStreamMergeAsyncEnumerator<T>:IStreamMergeAsyncEnumerator<T>
|
||||
{
|
||||
private readonly IStreamMergeAsyncEnumerator<T> _inMemoryStreamMergeAsyncEnumerator;
|
||||
private bool _first = true;
|
||||
private IEnumerator<T> _reverseEnumerator = Enumerable.Empty<T>().GetEnumerator();
|
||||
public InMemoryReverseStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<T> inMemoryStreamMergeAsyncEnumerator)
|
||||
{
|
||||
_inMemoryStreamMergeAsyncEnumerator = inMemoryStreamMergeAsyncEnumerator;
|
||||
}
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await _inMemoryStreamMergeAsyncEnumerator.DisposeAsync();
|
||||
_reverseEnumerator.Dispose();
|
||||
}
|
||||
|
||||
public async ValueTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (_first)
|
||||
{
|
||||
ICollection<T> _reverseCollection = new LinkedList<T>();
|
||||
while(await _inMemoryStreamMergeAsyncEnumerator.MoveNextAsync())
|
||||
{
|
||||
_reverseCollection.Add(_inMemoryStreamMergeAsyncEnumerator.Current);
|
||||
}
|
||||
|
||||
_reverseEnumerator = _reverseCollection.Reverse().GetEnumerator();
|
||||
_first = false;
|
||||
}
|
||||
|
||||
return _reverseEnumerator.MoveNext();
|
||||
}
|
||||
|
||||
public T Current => _reverseEnumerator.Current;
|
||||
public bool SkipFirst()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool HasElement()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T ReallyCurrent => Current;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ShardingCore.Core;
|
||||
|
||||
namespace ShardingCore.Sharding.PaginationConfigurations
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/1 17:32:36
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public interface IPaginationConfiguration<TEntity> where TEntity : class,IShardingTable
|
||||
{
|
||||
void Configure(PaginationBuilder<TEntity> builder);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Core;
|
||||
|
||||
namespace ShardingCore.Sharding.PaginationConfigurations
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/1 17:33:12
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class PaginationBuilder<TEntity> where TEntity:class,IShardingTable
|
||||
{
|
||||
private readonly PaginationMetadata _metadata;
|
||||
|
||||
public PaginationBuilder(PaginationMetadata metadata)
|
||||
{
|
||||
_metadata = metadata;
|
||||
}
|
||||
/// <summary>
|
||||
/// 分页顺序
|
||||
/// </summary>
|
||||
/// <param name="orderPropertyExpression"></param>
|
||||
/// <typeparam name="TProperty"></typeparam>
|
||||
public PaginationOrderPropertyBuilder PaginationSequence<TProperty>(Expression<Func<TEntity, TProperty>> orderPropertyExpression)
|
||||
{
|
||||
return new PaginationOrderPropertyBuilder(orderPropertyExpression, _metadata);
|
||||
}
|
||||
/// <summary>
|
||||
/// 配置反向排序 仅支持单排序 当skip>= reverseTotalGe*reverseFactor使用反向排序
|
||||
/// </summary>
|
||||
/// <param name="reverseFactor"></param>
|
||||
/// <param name="reverseTotalGe"></param>
|
||||
/// <returns></returns>
|
||||
public PaginationBuilder<TEntity> ConfigReverseShardingPage(double reverseFactor=0.5,long reverseTotalGe=10000L)
|
||||
{
|
||||
_metadata.ReverseFactor = reverseFactor;
|
||||
_metadata.ReverseTotalGe = reverseTotalGe;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 配置当分表数目小于多少后直接取到内存不在流式处理
|
||||
/// </summary>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
public PaginationBuilder<TEntity> ConfigTakeInMemoryCountIfLe(int count)
|
||||
{
|
||||
_metadata.TakeInMemoryCountIfLe = count;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
|
||||
namespace ShardingCore.Sharding.PaginationConfigurations
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 7:45:55
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class PaginationConfig
|
||||
{
|
||||
public PaginationConfig(LambdaExpression orderPropertyExpression, PaginationMatchEnum paginationMatchEnum= PaginationMatchEnum.Owner, IComparer<string> tailComparer=null)
|
||||
{
|
||||
OrderPropertyExpression = orderPropertyExpression;
|
||||
OrderPropertyInfo = orderPropertyExpression.GetPropertyAccess();
|
||||
PropertyName = OrderPropertyInfo.Name;
|
||||
PaginationMatchEnum = paginationMatchEnum;
|
||||
TailComparer = tailComparer ?? Comparer<string>.Default;
|
||||
}
|
||||
|
||||
public LambdaExpression OrderPropertyExpression { get; set; }
|
||||
public IComparer<string> TailComparer { get; set; }
|
||||
public PaginationMatchEnum PaginationMatchEnum { get; set; }
|
||||
public PropertyInfo OrderPropertyInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 如果查询没发现排序就将当前配置追加上去
|
||||
/// </summary>
|
||||
public bool AppendIfOrderNone => AppendOrder >= 0;
|
||||
/// <summary>
|
||||
/// 大于等于0表示需要
|
||||
/// </summary>
|
||||
public int AppendOrder { get; set; } = -1;
|
||||
public string PropertyName { get;}
|
||||
|
||||
|
||||
protected bool Equals(PaginationConfig other)
|
||||
{
|
||||
return PropertyName == other.PropertyName;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((PaginationConfig) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (PropertyName != null ? PropertyName.GetHashCode() : 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
|
||||
namespace ShardingCore.Sharding.PaginationConfigurations
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Wednesday, 01 September 2021 21:27:25
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
[Flags]
|
||||
public enum PaginationMatchEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 必须是当前对象的属性
|
||||
/// </summary>
|
||||
Owner = 1,
|
||||
/// <summary>
|
||||
/// 只要名称一样就可以了
|
||||
/// </summary>
|
||||
Named = 1 << 1,
|
||||
/// <summary>
|
||||
/// 仅第一个匹配就可以了
|
||||
/// </summary>
|
||||
PrimaryMatch = 1 << 2
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ShardingCore.Sharding.PaginationConfigurations
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 7:45:16
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
/// <summary>
|
||||
/// 分页配置元数据
|
||||
/// </summary>
|
||||
public class PaginationMetadata
|
||||
{
|
||||
public ISet<PaginationConfig> PaginationConfigs = new HashSet<PaginationConfig>();
|
||||
|
||||
/// <summary>
|
||||
/// 反向排序因子
|
||||
/// </summary>
|
||||
public double ReverseFactor { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 当条数大于多少条后采用反向排序
|
||||
/// </summary>
|
||||
public long ReverseTotalGe { get; set; } = 10000L;
|
||||
/// <summary>
|
||||
/// 是否已开启反向排序 仅支持单排序
|
||||
/// </summary>
|
||||
public bool EnableReverseShardingPage => ReverseFactor > 0 && ReverseFactor < 1 && ReverseTotalGe >= 1000;
|
||||
/// <summary>
|
||||
/// 分表发现如果少于多少条后直接取到内存 LESS THAN OR EQUAL
|
||||
/// </summary>
|
||||
public int TakeInMemoryCountIfLe { get; set; } = 100;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace ShardingCore.Sharding.PaginationConfigurations
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Wednesday, 01 September 2021 21:32:53
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class PaginationOrderPropertyBuilder
|
||||
{
|
||||
private readonly PaginationConfig _paginationConfig;
|
||||
|
||||
public PaginationOrderPropertyBuilder(LambdaExpression orderPropertyExpression,PaginationMetadata metadata)
|
||||
{
|
||||
_paginationConfig = new PaginationConfig(orderPropertyExpression);
|
||||
metadata.PaginationConfigs.Add(_paginationConfig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用哪个后缀比较
|
||||
/// </summary>
|
||||
/// <param name="tailComparer"></param>
|
||||
/// <returns></returns>
|
||||
public PaginationOrderPropertyBuilder UseTailCompare(IComparer<string> tailComparer)
|
||||
{
|
||||
|
||||
_paginationConfig.TailComparer= tailComparer ?? throw new ArgumentException(nameof(tailComparer));
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 使用哪种比较方式
|
||||
/// </summary>
|
||||
/// <param name="paginationMatchEnum"></param>
|
||||
/// <returns></returns>
|
||||
public PaginationOrderPropertyBuilder UseQueryMatch(PaginationMatchEnum paginationMatchEnum)
|
||||
{
|
||||
_paginationConfig.PaginationMatchEnum = paginationMatchEnum;
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
/// 如果查询没发现排序就将当前配置追加上去
|
||||
/// </summary>
|
||||
/// <param name="order">大于等于0生效,越大优先级越高</param>
|
||||
/// <returns></returns>
|
||||
public PaginationOrderPropertyBuilder UseAppendIfOrderNone(int order=0)
|
||||
{
|
||||
_paginationConfig.AppendOrder = order;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines;
|
||||
|
||||
namespace ShardingCore.Sharding.ShardingQueryExecutors
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/1 7:47:05
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class DefaultShardingQueryExecutor : IShardingQueryExecutor
|
||||
{
|
||||
private readonly IStreamMergeContextFactory _streamMergeContextFactory;
|
||||
|
||||
public DefaultShardingQueryExecutor(IStreamMergeContextFactory streamMergeContextFactory)
|
||||
{
|
||||
_streamMergeContextFactory = streamMergeContextFactory;
|
||||
}
|
||||
public TResult Execute<TResult>(ICurrentDbContext currentContext, Expression query)
|
||||
{
|
||||
var currentDbContext = currentContext.Context;
|
||||
|
||||
if (currentDbContext is IShardingDbContext shardingDbContext)
|
||||
{
|
||||
//如果根表达式为iqueryable表示需要迭代
|
||||
if (query.Type.HasImplementedRawGeneric(typeof(IQueryable<>)))
|
||||
{
|
||||
return EnumerableExecute<TResult>(shardingDbContext, query, false);
|
||||
}
|
||||
|
||||
return DoExecute<TResult>(shardingDbContext, query, false, default);
|
||||
}
|
||||
|
||||
throw new ShardingCoreException("db context operator is not IShardingDbContext");
|
||||
}
|
||||
|
||||
public TResult ExecuteAsync<TResult>(ICurrentDbContext currentContext, Expression query,CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var currentDbContext = currentContext.Context;
|
||||
if (currentDbContext is IShardingDbContext shardingDbContext)
|
||||
{
|
||||
if (typeof(TResult).HasImplementedRawGeneric(typeof(IAsyncEnumerable<>)))
|
||||
{
|
||||
|
||||
return EnumerableExecute<TResult>(shardingDbContext, query, true);
|
||||
|
||||
}
|
||||
|
||||
if (typeof(TResult).HasImplementedRawGeneric(typeof(Task<>)))
|
||||
{
|
||||
return DoExecute<TResult>(shardingDbContext, query, true, default);
|
||||
|
||||
}
|
||||
|
||||
|
||||
throw new ShardingCoreException($"db context operator not support query expression:[{query.ShardingPrint()}] result type:[{typeof(TResult).FullName}]");
|
||||
}
|
||||
|
||||
throw new ShardingCoreException("db context operator is not IShardingDbContext");
|
||||
}
|
||||
private TResult DoExecute<TResult>(IShardingDbContext shardingDbContext, Expression query, bool async, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
|
||||
if (query is MethodCallExpression methodCallExpression)
|
||||
{
|
||||
switch (methodCallExpression.Method.Name)
|
||||
{
|
||||
|
||||
case nameof(Enumerable.First):
|
||||
return GenericMergeExecute<TResult>(typeof(FirstAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.FirstOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(FirstOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Last):
|
||||
return GenericMergeExecute<TResult>(typeof(LastAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.LastOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(LastOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Single):
|
||||
return GenericMergeExecute<TResult>(typeof(SingleAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.SingleOrDefault):
|
||||
return GenericMergeExecute<TResult>(typeof(SingleOrDefaultAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Count):
|
||||
return EnsureMergeExecute<TResult>(typeof(CountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.LongCount):
|
||||
return EnsureMergeExecute<TResult>(typeof(LongCountAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Any):
|
||||
return EnsureMergeExecute<TResult>(typeof(AnyAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.All):
|
||||
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Max):
|
||||
return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Min):
|
||||
return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Sum):
|
||||
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Average):
|
||||
return EnsureMergeExecute2<TResult>(typeof(AverageAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
case nameof(Enumerable.Contains):
|
||||
return EnsureMergeExecute<TResult>(typeof(ContainsAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
throw new ShardingCoreException($"db context operator not support query expression:[{query.ShardingPrint()}] result type:[{typeof(TResult).FullName}]");
|
||||
}
|
||||
private TResult EnumerableExecute<TResult>(IShardingDbContext shardingDbContext, Expression query, bool async)
|
||||
{
|
||||
Type queryEntityType;
|
||||
if (async)
|
||||
queryEntityType = typeof(TResult).GetGenericArguments()[0];
|
||||
else
|
||||
{
|
||||
queryEntityType = query.Type.GetSequenceType();
|
||||
}
|
||||
Type type = typeof(EnumerableQuery<>);
|
||||
type = type.MakeGenericType(queryEntityType);
|
||||
var queryable = Activator.CreateInstance(type, query);
|
||||
|
||||
var streamMergeContextMethod = _streamMergeContextFactory.GetType().GetMethod("Create");
|
||||
if (streamMergeContextMethod == null)
|
||||
throw new ShardingCoreException("cant found IStreamMergeContextFactory method [Create]");
|
||||
var streamMergeContext = streamMergeContextMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(_streamMergeContextFactory, new[] { queryable, shardingDbContext });
|
||||
|
||||
|
||||
Type streamMergeEngineType = typeof(AsyncEnumerableStreamMergeEngine<>);
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
|
||||
return (TResult)Activator.CreateInstance(streamMergeEngineType, streamMergeContext);
|
||||
}
|
||||
|
||||
|
||||
private TResult GenericMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
|
||||
{
|
||||
var queryEntityType = query.GetQueryEntityType();
|
||||
var resultEntityType = query.GetResultType();
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
|
||||
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
|
||||
var methodName = async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult);
|
||||
var streamEngineMethod = streamMergeEngineType.GetMethod(methodName);
|
||||
if (streamEngineMethod == null)
|
||||
throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
|
||||
var @params = async ? new object[] { cancellationToken } : new object[0];
|
||||
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamEngine, @params);
|
||||
}
|
||||
private TResult GenericMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
|
||||
{
|
||||
var queryEntityType = query.GetQueryEntityType();
|
||||
var resultType = query.GetResultType();
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType, resultType);
|
||||
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
|
||||
var methodName = async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult);
|
||||
var streamEngineMethod = streamMergeEngineType.GetMethod(methodName);
|
||||
if (streamEngineMethod == null)
|
||||
throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
|
||||
var @params = async ? new object[] { cancellationToken } : new object[0];
|
||||
//typeof(TResult)==?resultType
|
||||
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params);
|
||||
}
|
||||
|
||||
|
||||
private TResult EnsureMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
|
||||
{
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType());
|
||||
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
|
||||
var methodName = async ? nameof(IEnsureMergeResult<object>.MergeResultAsync) : nameof(IEnsureMergeResult<object>.MergeResult);
|
||||
var streamEngineMethod = streamMergeEngineType.GetMethod(methodName);
|
||||
if (streamEngineMethod == null)
|
||||
throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
|
||||
var @params = async ? new object[] { cancellationToken } : new object[0];
|
||||
return (TResult)streamEngineMethod.Invoke(streamEngine, @params);
|
||||
}
|
||||
|
||||
private TResult EnsureMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
|
||||
{
|
||||
if (async)
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType(), typeof(TResult).GetGenericArguments()[0]);
|
||||
else
|
||||
streamMergeEngineType = streamMergeEngineType.MakeGenericType(query.GetQueryEntityType(), typeof(TResult));
|
||||
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
|
||||
var methodName = async
|
||||
? nameof(IEnsureMergeResult<object>.MergeResultAsync)
|
||||
: nameof(IEnsureMergeResult<object>.MergeResult);
|
||||
var streamEngineMethod = streamMergeEngineType.GetMethod(methodName);
|
||||
if (streamEngineMethod == null)
|
||||
throw new ShardingCoreException($"cant found InMemoryAsyncStreamMergeEngine method [{methodName}]");
|
||||
var @params = async ? new object[] { cancellationToken } : new object[0];
|
||||
return (TResult)streamEngineMethod.Invoke(streamEngine, @params);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.ShardingQueryExecutors
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/8/31 21:30:28
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class EnumeratorShardingQueryExecutor<TEntity>
|
||||
{
|
||||
private readonly StreamMergeContext<TEntity> _streamMergeContext;
|
||||
private readonly IShardingPageManager _shardingPageManager;
|
||||
private readonly IVirtualTableManager _virtualTableManager;
|
||||
|
||||
public EnumeratorShardingQueryExecutor(StreamMergeContext<TEntity> streamMergeContext)
|
||||
{
|
||||
_streamMergeContext = streamMergeContext;
|
||||
_shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
|
||||
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
|
||||
}
|
||||
public IEnumeratorStreamMergeEngine<TEntity> ExecuteAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
//操作单表
|
||||
if (!_streamMergeContext.IsShardingQuery())
|
||||
{
|
||||
return new SingleQueryEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext);
|
||||
}
|
||||
//未开启系统分表或者本次查询涉及多张分表
|
||||
if (_streamMergeContext.IsPaginationQuery()&&_streamMergeContext.IsSingleShardingTableQuery()&&_shardingPageManager.Current != null)
|
||||
{
|
||||
//获取虚拟表判断是否启用了分页配置
|
||||
var shardingEntityType = _streamMergeContext.RouteResults.First().ReplaceTables.First().EntityType;
|
||||
var virtualTable = _virtualTableManager.GetVirtualTable(_streamMergeContext.GetShardingDbContext().ShardingDbContextType, shardingEntityType);
|
||||
if (virtualTable.EnablePagination)
|
||||
{
|
||||
var paginationMetadata = virtualTable.PaginationMetadata;
|
||||
//判断本次查询的排序是否包含order,如果不包含就获取默认添加的排序
|
||||
if (_streamMergeContext.Orders.IsEmpty())
|
||||
{
|
||||
//除了判断属性名还要判断所属关系
|
||||
var appendPaginationConfig = paginationMetadata.PaginationConfigs.OrderByDescending(o=>o.AppendOrder)
|
||||
.FirstOrDefault(o => o.AppendIfOrderNone&&typeof(TEntity).ContainPropertyName(o.PropertyName)&& PaginationMatch(o));
|
||||
if (appendPaginationConfig != null)
|
||||
{
|
||||
return new AppenOrderSequenceEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext, appendPaginationConfig, _shardingPageManager.Current.RouteQueryResults);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var primaryOrder = _streamMergeContext.Orders.First();
|
||||
var appendPaginationConfig = paginationMetadata.PaginationConfigs.FirstOrDefault(o => PaginationMatch(o,primaryOrder));
|
||||
if (appendPaginationConfig != null)
|
||||
{
|
||||
return new SequenceEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext, appendPaginationConfig, _shardingPageManager.Current.RouteQueryResults, primaryOrder.IsAsc);
|
||||
}
|
||||
if (_streamMergeContext.Orders.Count() == 1)
|
||||
{
|
||||
//skip过大reserve skip
|
||||
if (paginationMetadata.EnableReverseShardingPage &&_streamMergeContext.Take.GetValueOrDefault()>0)
|
||||
{
|
||||
var total = _shardingPageManager.Current.RouteQueryResults.Sum(o => o.QueryResult);
|
||||
if (paginationMetadata.IsUseReverse(_streamMergeContext.Skip.GetValueOrDefault(), total))
|
||||
{
|
||||
return new ReverseShardingEnumeratorAsyncStreamMergeEngine<TEntity>(
|
||||
_streamMergeContext, primaryOrder, total);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new DefaultShardingEnumeratorAsyncStreamMergeEngine<TEntity>(_streamMergeContext);
|
||||
}
|
||||
|
||||
private bool PaginationMatch(PaginationConfig paginationConfig)
|
||||
{
|
||||
if (paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.Owner)&& !paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.Named))
|
||||
return typeof(TEntity) == paginationConfig.OrderPropertyInfo.DeclaringType;
|
||||
|
||||
return false;
|
||||
}
|
||||
private bool PaginationMatch(PaginationConfig paginationConfig,PropertyOrder propertyOrder)
|
||||
{
|
||||
if (paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.PrimaryMatch))
|
||||
{
|
||||
if (!propertyOrder.PropertyExpression.StartsWith(paginationConfig.PropertyName))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (propertyOrder.PropertyExpression != paginationConfig.PropertyName)
|
||||
return false;
|
||||
|
||||
if (paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.Owner)&&!paginationConfig.PaginationMatchEnum.HasFlag(PaginationMatchEnum.Named))
|
||||
return typeof(TEntity) == paginationConfig.OrderPropertyInfo.DeclaringType;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -31,10 +31,11 @@ namespace ShardingCore.Sharding
|
|||
//public DataSourceRoutingResult RoutingResult { get; }
|
||||
public int? Skip { get;}
|
||||
public int? Take { get; }
|
||||
public IEnumerable<PropertyOrder> Orders { get;}
|
||||
public IEnumerable<PropertyOrder> Orders { get; private set; }
|
||||
|
||||
public SelectContext SelectContext { get;}
|
||||
public GroupByContext GroupByContext { get; }
|
||||
public IEnumerable<RouteResult> RouteResults { get; }
|
||||
|
||||
public StreamMergeContext(IQueryable<T> source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IRouteTailFactory routeTailFactory)
|
||||
{
|
||||
|
@ -50,6 +51,7 @@ namespace ShardingCore.Sharding
|
|||
SelectContext = reWriteResult.SelectContext;
|
||||
GroupByContext = reWriteResult.GroupByContext;
|
||||
_reWriteSource = reWriteResult.ReWriteQueryable;
|
||||
RouteResults = _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(), _source);
|
||||
}
|
||||
//public StreamMergeContext(IQueryable<T> source,IEnumerable<RouteResult> routeResults,
|
||||
// IShardingParallelDbContextFactory shardingParallelDbContextFactory,IShardingScopeFactory shardingScopeFactory)
|
||||
|
@ -66,16 +68,15 @@ namespace ShardingCore.Sharding
|
|||
// GroupByContext = reWriteResult.GroupByContext;
|
||||
// _reWriteSource = reWriteResult.ReWriteQueryable;
|
||||
//}
|
||||
|
||||
public void ReSetOrders(IEnumerable<PropertyOrder> orders)
|
||||
{
|
||||
Orders = orders;
|
||||
}
|
||||
public DbContext CreateDbContext(RouteResult routeResult)
|
||||
{
|
||||
var routeTail = _routeTailFactory.Create(routeResult);
|
||||
return _shardingDbContext.GetDbContext(false, routeTail);
|
||||
}
|
||||
public IEnumerable<RouteResult> GetRouteResults()
|
||||
{
|
||||
return _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(),_source);
|
||||
}
|
||||
|
||||
public IRouteTail Create(RouteResult routeResult)
|
||||
{
|
||||
|
@ -96,6 +97,12 @@ namespace ShardingCore.Sharding
|
|||
return Skip.HasValue || Take.HasValue;
|
||||
}
|
||||
|
||||
public bool IsPaginationQuery()
|
||||
{
|
||||
return Skip.GetValueOrDefault() > 0 || Take.GetValueOrDefault() > 0;
|
||||
}
|
||||
|
||||
|
||||
public bool HasGroupQuery()
|
||||
{
|
||||
return this.GroupByContext.GroupExpression != null;
|
||||
|
@ -106,5 +113,10 @@ namespace ShardingCore.Sharding
|
|||
return this.SelectContext.SelectProperties.Any(o => o.IsAggregateMethod);
|
||||
}
|
||||
|
||||
public IShardingDbContext GetShardingDbContext()
|
||||
{
|
||||
return _shardingDbContext;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
|
|||
}
|
||||
_constantItem = (TEntity)constantExpression.Value;
|
||||
}
|
||||
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression)
|
||||
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> queryable, Expression secondExpression)
|
||||
{
|
||||
if (!(secondExpression is ConstantExpression))
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
|
|||
{
|
||||
}
|
||||
|
||||
public override IQueryable EFQueryAfterFilter<TResult1>(IQueryable<TEntity> queryable)
|
||||
public override IQueryable DoCombineQueryable<TResult1>(IQueryable<TEntity> queryable)
|
||||
{
|
||||
var secondExpression = GetSecondExpression();
|
||||
if (secondExpression != null)
|
||||
|
@ -41,7 +41,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
|
|||
return queryable;
|
||||
}
|
||||
|
||||
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> _queryable, Expression secondExpression)
|
||||
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> _queryable, Expression secondExpression)
|
||||
{
|
||||
return _queryable;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
|
|||
_methodCallExpression = methodCallExpression;
|
||||
}
|
||||
|
||||
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression)
|
||||
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> queryable, Expression secondExpression)
|
||||
{
|
||||
if (secondExpression is UnaryExpression where && where.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, bool>> predicate)
|
||||
{
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
|
|||
{
|
||||
}
|
||||
|
||||
public override IQueryable EFQueryAfterFilter<TResult>(IQueryable<TEntity> queryable)
|
||||
public override IQueryable DoCombineQueryable<TResult>(IQueryable<TEntity> queryable)
|
||||
{
|
||||
var secondExpression = GetSecondExpression();
|
||||
if (secondExpression != null)
|
||||
|
@ -41,7 +41,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
|
|||
return queryable;
|
||||
}
|
||||
|
||||
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> _queryable, Expression secondExpression)
|
||||
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> _queryable, Expression secondExpression)
|
||||
{
|
||||
return _queryable;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
|
|||
_methodCallExpression = methodCallExpression;
|
||||
}
|
||||
|
||||
protected override IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression)
|
||||
protected override IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> queryable, Expression secondExpression)
|
||||
{
|
||||
if (secondExpression is UnaryExpression where)
|
||||
{
|
||||
|
|
|
@ -30,38 +30,43 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
|
|||
public AbstractInMemoryAsyncMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext)
|
||||
{
|
||||
_methodCallExpression = methodCallExpression;
|
||||
var expression = methodCallExpression.Arguments.FirstOrDefault(o => typeof(IQueryable).IsAssignableFrom(o.Type))
|
||||
#if !EFCORE2
|
||||
?? throw new InvalidOperationException(methodCallExpression.Print());
|
||||
#endif
|
||||
#if EFCORE2
|
||||
?? throw new InvalidOperationException(methodCallExpression.ToString());
|
||||
#endif
|
||||
_queryable = new EnumerableQuery<TEntity>(expression);
|
||||
_secondExpression = methodCallExpression.Arguments.FirstOrDefault(o => !typeof(IQueryable).IsAssignableFrom(o.Type));
|
||||
|
||||
if (_secondExpression != null)
|
||||
if (methodCallExpression.Arguments.Count < 1 || methodCallExpression.Arguments.Count > 2)
|
||||
throw new ArgumentException($"argument count must 1 or 2 :[{methodCallExpression.ShardingPrint()}]");
|
||||
for (int i = 0; i < methodCallExpression.Arguments.Count; i++)
|
||||
{
|
||||
_queryable = ProcessSecondExpression(_queryable, _secondExpression);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (methodCallExpression.Arguments.Count == 2)
|
||||
var expression = methodCallExpression.Arguments[i];
|
||||
if (typeof(IQueryable).IsAssignableFrom(expression.Type))
|
||||
{
|
||||
#if !EFCORE2
|
||||
throw new InvalidOperationException(methodCallExpression.Print());
|
||||
#endif
|
||||
#if EFCORE2
|
||||
throw new InvalidOperationException(methodCallExpression.ToString());
|
||||
#endif
|
||||
if (_queryable != null)
|
||||
throw new ArgumentException(
|
||||
$"argument found more 1 IQueryable :[{methodCallExpression.ShardingPrint()}]");
|
||||
_queryable = new EnumerableQuery<TEntity>(expression);
|
||||
}
|
||||
else
|
||||
{
|
||||
_secondExpression = expression;
|
||||
}
|
||||
}
|
||||
if(_queryable==null)
|
||||
throw new ArgumentException($"argument not found IQueryable :[{methodCallExpression.ShardingPrint()}]");
|
||||
if (methodCallExpression.Arguments.Count ==2)
|
||||
{
|
||||
if(_secondExpression == null)
|
||||
throw new InvalidOperationException(methodCallExpression.ShardingPrint());
|
||||
_queryable = CombineQueryable(_queryable, _secondExpression);
|
||||
}
|
||||
|
||||
|
||||
_mergeContext = ShardingContainer.GetService<IStreamMergeContextFactory>().Create(_queryable, shardingDbContext);
|
||||
_parllelDbbContexts = new List<DbContext>();
|
||||
}
|
||||
|
||||
protected abstract IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression);
|
||||
/// <summary>
|
||||
/// 合并queryable
|
||||
/// </summary>
|
||||
/// <param name="queryable"></param>
|
||||
/// <param name="secondExpression"></param>
|
||||
/// <returns></returns>
|
||||
protected abstract IQueryable<TEntity> CombineQueryable(IQueryable<TEntity> queryable, Expression secondExpression);
|
||||
|
||||
private IQueryable CreateAsyncExecuteQueryable<TResult>(RouteResult routeResult)
|
||||
{
|
||||
|
@ -69,13 +74,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
|
|||
_parllelDbbContexts.Add(shardingDbContext);
|
||||
var newQueryable = (IQueryable<TEntity>) GetStreamMergeContext().GetReWriteQueryable()
|
||||
.ReplaceDbContextQueryable(shardingDbContext);
|
||||
var newFilterQueryable = EFQueryAfterFilter<TResult>(newQueryable);
|
||||
return newFilterQueryable;
|
||||
var newCombineQueryable= DoCombineQueryable<TResult>(newQueryable);
|
||||
return newCombineQueryable
|
||||
;
|
||||
}
|
||||
|
||||
public async Task<List<TResult>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery, CancellationToken cancellationToken = new CancellationToken())
|
||||
public async Task<List<RouteQueryResult<TResult>>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var tableResult = _mergeContext.GetRouteResults();
|
||||
var tableResult = _mergeContext.RouteResults;
|
||||
var enumeratorTasks = tableResult.Select(routeResult =>
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
|
@ -83,7 +89,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
|
|||
try
|
||||
{
|
||||
var asyncExecuteQueryable = CreateAsyncExecuteQueryable<TResult>(routeResult);
|
||||
return await efQuery(asyncExecuteQueryable);
|
||||
var queryResult= await efQuery(asyncExecuteQueryable);
|
||||
return new RouteQueryResult<TResult>(routeResult, queryResult);
|
||||
//}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -99,7 +106,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
|
|||
|
||||
public List<TResult> Execute<TResult>(Func<IQueryable, TResult> efQuery, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var tableResult = _mergeContext.GetRouteResults();
|
||||
var tableResult = _mergeContext.RouteResults;
|
||||
var enumeratorTasks = tableResult.Select(routeResult =>
|
||||
{
|
||||
return Task.Run(() =>
|
||||
|
@ -121,7 +128,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
|
|||
}
|
||||
|
||||
|
||||
public virtual IQueryable EFQueryAfterFilter<TResult>(IQueryable<TEntity> queryable)
|
||||
public virtual IQueryable DoCombineQueryable<TResult>(IQueryable<TEntity> queryable)
|
||||
{
|
||||
return queryable;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
|
|||
public interface IInMemoryAsyncMergeEngine<TEntity>
|
||||
{
|
||||
StreamMergeContext<TEntity> GetStreamMergeContext();
|
||||
Task<List<TResult>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery,
|
||||
Task<List<RouteQueryResult<TResult>>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery,
|
||||
CancellationToken cancellationToken = new CancellationToken());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureExpressionMergeEngines;
|
||||
|
@ -32,120 +33,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
|
||||
public override TEnsureResult MergeResult()
|
||||
{
|
||||
if (typeof(decimal) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<decimal>)queryable).Average());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum() / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(decimal?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<decimal?>)queryable).Average()
|
||||
);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(int) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<int>)queryable).Average()
|
||||
);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum() / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(int?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<int?>)queryable).Average()
|
||||
);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(long) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<long>)queryable).Average()
|
||||
);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum() / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(long?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<long?>)queryable).Average()
|
||||
);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(double) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<double>)queryable).Average()
|
||||
);
|
||||
var average = result.Sum() / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(double?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<double?>)queryable).Average()
|
||||
);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(float) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<float>)queryable).Average()
|
||||
);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum() / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
if (typeof(float?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(
|
||||
queryable => ((IQueryable<float?>)queryable).Average()
|
||||
);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
throw new ShardingCoreException(
|
||||
$"not support {GetMethodCallExpression().Print()} result {typeof(TEnsureResult)}");
|
||||
#endif
|
||||
#if EFCORE2
|
||||
throw new ShardingCoreException(
|
||||
$"not support {GetMethodCallExpression()} result {typeof(TEnsureResult)}");
|
||||
#endif
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync());
|
||||
}
|
||||
|
||||
public override async Task<TEnsureResult> MergeResultAsync(
|
||||
|
@ -158,7 +46,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum() / result.Count;
|
||||
var average = result.Sum(o=>o.QueryResult) / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -169,7 +57,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
var average = sum.HasValue ? sum / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -180,7 +69,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum() / result.Count;
|
||||
var average = result.Sum(o => o.QueryResult) / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -191,7 +80,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
var average = sum.HasValue ? sum / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -202,7 +92,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum() / result.Count;
|
||||
var average = result.Sum(o => o.QueryResult) / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -213,7 +103,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
var average = sum.HasValue ? sum / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -222,7 +113,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(
|
||||
queryable => ((IQueryable<double>)queryable).AverageAsync(cancellationToken),
|
||||
cancellationToken);
|
||||
var average = result.Sum() / result.Count;
|
||||
var average = result.Sum(o => o.QueryResult) / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -233,7 +124,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
var average = sum.HasValue ? sum / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -244,7 +136,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum() / result.Count;
|
||||
var average = result.Sum(o => o.QueryResult) / result.Count;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
|
@ -255,18 +147,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var average = result.Sum().HasValue ? result.Sum() / result.Count : default;
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
var average = sum.HasValue ? sum / result.Count : default;
|
||||
return ConvertSum(average);
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
throw new ShardingCoreException(
|
||||
$"not support {GetMethodCallExpression().Print()} result {typeof(TEnsureResult)}");
|
||||
#endif
|
||||
#if EFCORE2
|
||||
throw new ShardingCoreException(
|
||||
$"not support {GetMethodCallExpression()} result {typeof(TEnsureResult)}");
|
||||
#endif
|
||||
$"not support {GetMethodCallExpression().ShardingPrint()} result {typeof(TEnsureResult)}");
|
||||
}
|
||||
|
||||
private TEnsureResult ConvertSum<TNumber>(TNumber number)
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Text;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
|
||||
|
@ -27,14 +28,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
|
||||
public override TResult MergeResult<TResult>()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).Max());
|
||||
return result.Max();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
|
||||
}
|
||||
|
||||
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).MaxAsync(cancellationToken), cancellationToken);
|
||||
return result.Max();
|
||||
return result.Max(o=>o.QueryResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
|
||||
|
@ -28,14 +29,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
|
||||
public override TResult MergeResult<TResult>()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).Min());
|
||||
return result.Min();
|
||||
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
|
||||
}
|
||||
|
||||
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).MinAsync(cancellationToken), cancellationToken);
|
||||
return result.Min();
|
||||
return result.Min(o=>o.QueryResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureExpressionMergeEngines;
|
||||
|
@ -30,94 +31,8 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
|
||||
public override TEnsureResult MergeResult()
|
||||
{
|
||||
if (typeof(decimal) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<decimal>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(decimal?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<decimal?>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(int) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<int>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(int?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<int?>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(long) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<long>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(long?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<long?>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(double) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<double>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(double?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<double?>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(float) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<float>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(float?) == typeof(TEnsureResult))
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<float?>)queryable).Sum());
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
#if !EFCORE2
|
||||
throw new ShardingCoreException(
|
||||
$"not support {GetMethodCallExpression().Print()} result {typeof(TEnsureResult)}");
|
||||
#endif
|
||||
#if EFCORE2
|
||||
throw new ShardingCoreException(
|
||||
$"not support {GetMethodCallExpression()} result {typeof(TEnsureResult)}");
|
||||
#endif
|
||||
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync());
|
||||
}
|
||||
|
||||
public override async Task<TEnsureResult> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
|
@ -127,7 +42,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<decimal>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o=>o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(decimal?) == typeof(TEnsureResult))
|
||||
|
@ -135,7 +50,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<decimal?>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o=>o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(int) == typeof(TEnsureResult))
|
||||
|
@ -143,7 +58,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<int>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o=>o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(int?) == typeof(TEnsureResult))
|
||||
|
@ -151,7 +66,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<int?>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(long) == typeof(TEnsureResult))
|
||||
|
@ -159,7 +74,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<long>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(long?) == typeof(TEnsureResult))
|
||||
|
@ -167,7 +82,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<long?>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(double) == typeof(TEnsureResult))
|
||||
|
@ -175,7 +90,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<double>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(double?) == typeof(TEnsureResult))
|
||||
|
@ -183,7 +98,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<double?>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(float) == typeof(TEnsureResult))
|
||||
|
@ -191,7 +106,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<float>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
if (typeof(float?) == typeof(TEnsureResult))
|
||||
|
@ -199,18 +114,12 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
|
|||
var result = await base.ExecuteAsync(queryable => ((IQueryable<float?>)queryable).SumAsync(cancellationToken), cancellationToken);
|
||||
if (result.IsEmpty())
|
||||
return default;
|
||||
var sum = result.Sum();
|
||||
var sum = result.Sum(o => o.QueryResult);
|
||||
return ConvertSum(sum);
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
throw new ShardingCoreException(
|
||||
$"not support {GetMethodCallExpression().Print()} result {typeof(TEnsureResult)}");
|
||||
#endif
|
||||
#if EFCORE2
|
||||
throw new ShardingCoreException(
|
||||
$"not support {GetMethodCallExpression()} result {typeof(TEnsureResult)}");
|
||||
#endif
|
||||
$"not support {GetMethodCallExpression().ShardingPrint()} result {typeof(TEnsureResult)}");
|
||||
}
|
||||
private TEnsureResult ConvertSum<TNumber>(TNumber number)
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
|
@ -29,9 +30,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override bool MergeResult()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).Any());
|
||||
|
||||
return result.All(o => o);
|
||||
return AsyncHelper.RunSync(()=> MergeResultAsync());
|
||||
}
|
||||
|
||||
public override async Task<bool> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
|
@ -39,7 +38,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).AnyAsync(cancellationToken), cancellationToken);
|
||||
|
||||
return result.All(o => o);
|
||||
return result.All(o => o.QueryResult);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
|
@ -29,16 +30,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override bool MergeResult()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).Any());
|
||||
|
||||
return result.Any(o => o);
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync());
|
||||
}
|
||||
|
||||
public override async Task<bool> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).AnyAsync(cancellationToken), cancellationToken);
|
||||
|
||||
return result.Any(o => o);
|
||||
return result.Any(o => o.QueryResult);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ using ShardingCore.Extensions;
|
|||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeSync;
|
||||
using ShardingCore.Sharding.ShardingQueryExecutors;
|
||||
|
||||
#if EFCORE2
|
||||
using Microsoft.EntityFrameworkCore.Extensions.Internal;
|
||||
|
@ -24,15 +25,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
* @Date: Saturday, 14 August 2021 22:07:28
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class AsyncEnumerableStreamMergeEngine<T> : IAsyncEnumerable<T>, IEnumerable<T>, IDisposable
|
||||
public class AsyncEnumerableStreamMergeEngine<T> : IAsyncEnumerable<T>, IEnumerable<T>
|
||||
{
|
||||
private readonly StreamMergeContext<T> _mergeContext;
|
||||
private readonly ICollection<DbContext> _parllelDbbContexts;
|
||||
|
||||
public AsyncEnumerableStreamMergeEngine(StreamMergeContext<T> mergeContext)
|
||||
{
|
||||
_mergeContext = mergeContext;
|
||||
_parllelDbbContexts = new LinkedList<DbContext>();
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,7 +43,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
await enumator.MoveNextAsync();
|
||||
return enumator;
|
||||
}
|
||||
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
return new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync(cancellationToken)
|
||||
.GetAsyncEnumerator(cancellationToken);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EFCORE2
|
||||
private async Task<IAsyncEnumerator<T>> GetAsyncEnumerator(IQueryable<T> newQueryable)
|
||||
{
|
||||
|
@ -52,62 +57,12 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
await enumator.MoveNext();
|
||||
return enumator;
|
||||
}
|
||||
#endif
|
||||
#if !EFCORE2
|
||||
|
||||
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
return GetShardingEnumerator();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EFCORE2
|
||||
IAsyncEnumerator<T> IAsyncEnumerable<T>.GetEnumerator()
|
||||
{
|
||||
return GetShardingEnumerator();
|
||||
}
|
||||
#endif
|
||||
|
||||
private IQueryable<T> CreateAsyncExecuteQueryable(RouteResult routeResult,int routeCount)
|
||||
{
|
||||
var shardingDbContext = _mergeContext.CreateDbContext(routeResult);
|
||||
var useOriginal = routeCount>1;
|
||||
_parllelDbbContexts.Add(shardingDbContext);
|
||||
var newQueryable = (IQueryable<T>)(useOriginal?_mergeContext.GetReWriteQueryable():_mergeContext.GetOriginalQueryable())
|
||||
.ReplaceDbContextQueryable(shardingDbContext);
|
||||
return newQueryable;
|
||||
}
|
||||
|
||||
private IAsyncEnumerator<T> GetShardingEnumerator()
|
||||
{
|
||||
var tableResult = _mergeContext.GetRouteResults();
|
||||
var routeCount = tableResult.Count();
|
||||
var enumeratorTasks = tableResult.Select(routeResult =>
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var newQueryable = CreateAsyncExecuteQueryable(routeResult, routeCount);
|
||||
|
||||
var asyncEnumerator = await GetAsyncEnumerator(newQueryable);
|
||||
return new StreamMergeAsyncEnumerator<T>(asyncEnumerator);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}).ToArray();
|
||||
|
||||
var streamEnumerators = Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult();
|
||||
if (routeCount>1&&_mergeContext.HasSkipTake())
|
||||
return new PaginationStreamMergeAsyncEnumerator<T>(_mergeContext, streamEnumerators);
|
||||
if (_mergeContext.HasGroupQuery())
|
||||
return new MultiAggregateOrderStreamMergeAsyncEnumerator<T>(_mergeContext, streamEnumerators);
|
||||
return new MultiOrderStreamMergeAsyncEnumerator<T>(_mergeContext, streamEnumerators);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private IEnumerator<T> GetEnumerator(IQueryable<T> newQueryable)
|
||||
|
@ -119,33 +74,9 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
var tableResult = _mergeContext.GetRouteResults();
|
||||
var routeCount = tableResult.Count();
|
||||
var enumeratorTasks = tableResult.Select(routeResult =>
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var newQueryable = CreateAsyncExecuteQueryable(routeResult, routeCount);
|
||||
|
||||
var enumerator = GetEnumerator(newQueryable);
|
||||
return new StreamMergeEnumerator<T>(enumerator);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}).ToArray();
|
||||
|
||||
var streamEnumerators = Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult();
|
||||
if (routeCount > 1 && _mergeContext.HasSkipTake())
|
||||
return new PaginationStreamMergeEnumerator<T>(_mergeContext, streamEnumerators);
|
||||
if (_mergeContext.HasGroupQuery())
|
||||
return new MultiAggregateOrderStreamMergeEnumerator<T>(_mergeContext, streamEnumerators);
|
||||
return new MultiOrderStreamMergeEnumerator<T>(_mergeContext, streamEnumerators);
|
||||
return new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync()
|
||||
.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
|
@ -153,22 +84,5 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_parllelDbbContexts.IsNotEmpty())
|
||||
{
|
||||
_parllelDbbContexts.ForEach(o =>
|
||||
{
|
||||
try
|
||||
{
|
||||
o.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using System.Linq.Expressions;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureExpressionMergeEngines;
|
||||
|
@ -25,16 +26,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override bool MergeResult()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).Contains(GetConstantItem()));
|
||||
|
||||
return result.Any(o => o);
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync());
|
||||
}
|
||||
|
||||
public override async Task<bool> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).ContainsAsync(GetConstantItem(), cancellationToken), cancellationToken);
|
||||
|
||||
return result.Any(o => o);
|
||||
return result.Any(o => o.QueryResult);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureExpressionMergeEngines;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines
|
||||
|
@ -18,22 +19,29 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
*/
|
||||
public class CountAsyncInMemoryMergeEngine<TEntity> : AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine<TEntity,int>
|
||||
{
|
||||
private readonly IShardingPageManager _shardingPageManager;
|
||||
public CountAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
|
||||
{
|
||||
_shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
|
||||
}
|
||||
|
||||
public override int MergeResult()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).Count());
|
||||
|
||||
return result.Sum();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync());
|
||||
}
|
||||
|
||||
public override async Task<int> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).CountAsync(cancellationToken), cancellationToken);
|
||||
|
||||
return result.Sum();
|
||||
if (_shardingPageManager.Current != null)
|
||||
{
|
||||
foreach (var routeQueryResult in result)
|
||||
{
|
||||
_shardingPageManager.Current.RouteQueryResults.Add(new RouteQueryResult<long>(routeQueryResult.RouteResult, routeQueryResult.QueryResult));
|
||||
}
|
||||
}
|
||||
return result.Sum(o=>o.QueryResult);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 15:38:05
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public abstract class AbstractEnumeratorAsyncStreamMergeEngine<TEntity>: AbstractEnumeratorStreamMergeEngine<TEntity>
|
||||
{
|
||||
public AbstractEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
|
||||
{
|
||||
}
|
||||
|
||||
public override IAsyncEnumerator<TEntity> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var dbStreamMergeAsyncEnumerators = GetDbStreamMergeAsyncEnumerators();
|
||||
if (dbStreamMergeAsyncEnumerators.IsEmpty())
|
||||
throw new ShardingCoreException("GetDbStreamMergeAsyncEnumerators empty");
|
||||
return GetStreamMergeAsyncEnumerator(dbStreamMergeAsyncEnumerators);
|
||||
}
|
||||
|
||||
public abstract IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators();
|
||||
public abstract IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators);
|
||||
public async Task<IAsyncEnumerator<TEntity>> DoGetAsyncEnumerator(IQueryable<TEntity> newQueryable)
|
||||
{
|
||||
var enumator = newQueryable.AsAsyncEnumerable().GetAsyncEnumerator();
|
||||
await enumator.MoveNextAsync();
|
||||
return enumator;
|
||||
}
|
||||
// public virtual IQueryable<TEntity> CreateAsyncExecuteQueryable(RouteResult routeResult)
|
||||
// {
|
||||
// var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
|
||||
// var useOriginal = StreamMergeContext > 1;
|
||||
// DbContextQueryStore.TryAdd(routeResult,shardingDbContext);
|
||||
// var newQueryable = (IQueryable<TEntity>)(useOriginal ? StreamMergeContext.GetReWriteQueryable() : StreamMergeContext.GetOriginalQueryable())
|
||||
// .ReplaceDbContextQueryable(shardingDbContext);
|
||||
// return newQueryable;
|
||||
// }
|
||||
|
||||
public override IEnumerator<TEntity> GetEnumerator()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
using ShardingCore.Extensions;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 15:35:39
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public abstract class AbstractEnumeratorStreamMergeEngine<TEntity>:IEnumeratorStreamMergeEngine<TEntity>
|
||||
{
|
||||
public StreamMergeContext<TEntity> StreamMergeContext { get; }
|
||||
public ConcurrentDictionary<RouteResult,DbContext> DbContextQueryStore { get; }
|
||||
|
||||
public AbstractEnumeratorStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext)
|
||||
{
|
||||
StreamMergeContext = streamMergeContext;
|
||||
DbContextQueryStore = new ConcurrentDictionary<RouteResult, DbContext>();
|
||||
}
|
||||
|
||||
public abstract IAsyncEnumerator<TEntity> GetAsyncEnumerator(
|
||||
CancellationToken cancellationToken = new CancellationToken());
|
||||
|
||||
public abstract IEnumerator<TEntity> GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (DbContextQueryStore.IsNotEmpty())
|
||||
{
|
||||
DbContextQueryStore.Values.ForEach(dbContext =>
|
||||
{
|
||||
dbContext.Dispose();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 15:38:13
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class AbstractEnumeratorSyncStreamMergeEngine<TEntity> : AbstractEnumeratorStreamMergeEngine<TEntity>
|
||||
{
|
||||
public AbstractEnumeratorSyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
|
||||
{
|
||||
}
|
||||
|
||||
public override IAsyncEnumerator<TEntity> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IEnumerator<TEntity> GetEnumerator()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 15:15:34
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public interface IEnumeratorStreamMergeEngine<TEntity> : IAsyncEnumerable<TEntity>, IEnumerable<TEntity>, IDisposable
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Base;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/3 8:09:18
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class AppenOrderSequenceEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
|
||||
{
|
||||
private readonly PaginationConfig _appendPaginationConfig;
|
||||
private readonly ICollection<RouteQueryResult<long>> _routeQueryResults;
|
||||
private IShardingPageManager _shardingPageManager;
|
||||
private IVirtualTableManager _virtualTableManager;
|
||||
public AppenOrderSequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PaginationConfig appendPaginationConfig, ICollection<RouteQueryResult<long>> routeQueryResults) : base(streamMergeContext)
|
||||
{
|
||||
_appendPaginationConfig = appendPaginationConfig;
|
||||
_routeQueryResults = routeQueryResults;
|
||||
_shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
|
||||
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
|
||||
{
|
||||
var noPaginationQueryable = StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake();
|
||||
var skip = StreamMergeContext.Skip.GetValueOrDefault();
|
||||
if (skip < 0)
|
||||
throw new ShardingCoreException("skip must ge 0");
|
||||
|
||||
var take = StreamMergeContext.Take;
|
||||
if (take.HasValue&&take.Value <= 0)
|
||||
throw new ShardingCoreException("take must gt 0");
|
||||
|
||||
var sortRouteResults = _routeQueryResults.Select(o => new
|
||||
{
|
||||
Tail = o.RouteResult.ReplaceTables.First().Tail,
|
||||
RouteQueryResult = o
|
||||
}).OrderBy(o => o.Tail, _appendPaginationConfig.TailComparer).ToList();
|
||||
var skipCount = skip;
|
||||
|
||||
var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o=>o.RouteQueryResult)).Skip(skip).Take(take).ToList();
|
||||
|
||||
StreamMergeContext.ReSetOrders(new PropertyOrder[] { new PropertyOrder(_appendPaginationConfig.PropertyName, true) });
|
||||
var enumeratorTasks = sequenceResults.Select(sequenceResult =>
|
||||
{
|
||||
var newQueryable = CreateAsyncExecuteQueryable(noPaginationQueryable, sequenceResult);
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var asyncEnumerator = await DoGetAsyncEnumerator(newQueryable);
|
||||
return new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}).ToArray();
|
||||
|
||||
var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException();
|
||||
return streamEnumerators;
|
||||
}
|
||||
|
||||
private IQueryable<TEntity> CreateAsyncExecuteQueryable(IQueryable<TEntity> noPaginationQueryable, SequenceResult sequenceResult)
|
||||
{
|
||||
var shardingDbContext = StreamMergeContext.CreateDbContext(sequenceResult.RouteResult);
|
||||
DbContextQueryStore.TryAdd(sequenceResult.RouteResult, shardingDbContext);
|
||||
var newQueryable = (IQueryable<TEntity>)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take).OrderWithExpression(new PropertyOrder[]{new PropertyOrder(_appendPaginationConfig.PropertyName,true)}))
|
||||
.ReplaceDbContextQueryable(shardingDbContext);
|
||||
return newQueryable;
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
|
||||
{
|
||||
if (StreamMergeContext.HasGroupQuery())
|
||||
return new MultiAggregateOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Base
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/3 8:31:20
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SequencePaginationList
|
||||
{
|
||||
private readonly IEnumerable<RouteQueryResult<long>> _routeQueryResults;
|
||||
private long? _skip;
|
||||
private long? _take;
|
||||
|
||||
public SequencePaginationList(IEnumerable<RouteQueryResult<long>> routeQueryResults)
|
||||
{
|
||||
_routeQueryResults = routeQueryResults;
|
||||
}
|
||||
public SequencePaginationList Skip(long? skip)
|
||||
{
|
||||
_skip = skip;
|
||||
return this;
|
||||
}
|
||||
public SequencePaginationList Take(long? take)
|
||||
{
|
||||
_take = take;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICollection<SequenceResult> ToList()
|
||||
{
|
||||
ICollection<SequenceResult> routeResults = new LinkedList<SequenceResult>();
|
||||
|
||||
var currentSkip = _skip.GetValueOrDefault();
|
||||
var currentTake = _take;
|
||||
bool stopSkip = false;
|
||||
bool needBreak = false;
|
||||
foreach (var routeQueryResult in _routeQueryResults)
|
||||
{
|
||||
if (!stopSkip)
|
||||
{
|
||||
if (routeQueryResult.QueryResult >= currentSkip)
|
||||
{
|
||||
stopSkip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSkip = currentSkip - routeQueryResult.QueryResult;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var currentRealSkip = currentSkip;
|
||||
var currentRealTake = routeQueryResult.QueryResult-currentSkip;
|
||||
if (currentSkip != 0)
|
||||
currentSkip = 0;
|
||||
if (currentTake.HasValue)
|
||||
{
|
||||
if (currentTake.Value <= currentRealTake)
|
||||
{
|
||||
currentRealTake = currentTake.Value;
|
||||
needBreak = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentRealTake = currentTake.Value-currentRealTake;
|
||||
}
|
||||
}
|
||||
var sequenceResult = new SequenceResult(currentRealSkip, currentRealTake, routeQueryResult.RouteResult);
|
||||
routeResults.Add(sequenceResult);
|
||||
|
||||
if (needBreak)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return routeResults;
|
||||
}
|
||||
}
|
||||
public class SequenceResult
|
||||
{
|
||||
public SequenceResult(long skip, long take, RouteResult routeResult)
|
||||
{
|
||||
Skip = (int)skip;
|
||||
Take = (int)take;
|
||||
RouteResult = routeResult;
|
||||
}
|
||||
|
||||
public int Skip { get; }
|
||||
public int Take { get; }
|
||||
|
||||
public RouteResult RouteResult { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 16:16:12
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class DefaultShardingEnumeratorAsyncStreamMergeEngine<TEntity>:AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
|
||||
{
|
||||
public DefaultShardingEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
|
||||
{
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
|
||||
{
|
||||
var tableResult = StreamMergeContext.RouteResults;
|
||||
var enumeratorTasks = tableResult.Select(routeResult =>
|
||||
{
|
||||
var newQueryable = CreateAsyncExecuteQueryable(routeResult);
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var asyncEnumerator = await DoGetAsyncEnumerator(newQueryable);
|
||||
return new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}).ToArray();
|
||||
|
||||
var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException();
|
||||
return streamEnumerators;
|
||||
}
|
||||
|
||||
private IQueryable<TEntity> CreateAsyncExecuteQueryable(RouteResult routeResult)
|
||||
{
|
||||
var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
|
||||
DbContextQueryStore.TryAdd(routeResult, shardingDbContext);
|
||||
var newQueryable = (IQueryable<TEntity>)StreamMergeContext.GetReWriteQueryable()
|
||||
.ReplaceDbContextQueryable(shardingDbContext);
|
||||
return newQueryable;
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
|
||||
{
|
||||
if (StreamMergeContext.IsPaginationQuery())
|
||||
return new PaginationStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
if (StreamMergeContext.HasGroupQuery())
|
||||
return new MultiAggregateOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/3 13:32:12
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ReverseShardingEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
|
||||
{
|
||||
private readonly PropertyOrder _primaryOrder;
|
||||
private readonly long _total;
|
||||
|
||||
public ReverseShardingEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PropertyOrder primaryOrder, long total) : base(streamMergeContext)
|
||||
{
|
||||
_primaryOrder = primaryOrder;
|
||||
_total = total;
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
|
||||
{
|
||||
|
||||
var noPaginationNoOrderQueryable = _primaryOrder.IsAsc ? StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake().RemoveOrderBy(): StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake().RemoveOrderByDescending();
|
||||
var skip = StreamMergeContext.Skip.GetValueOrDefault();
|
||||
var take = StreamMergeContext.Take.GetValueOrDefault();
|
||||
var realSkip = _total- take- skip;
|
||||
var tableResult = StreamMergeContext.RouteResults;
|
||||
var reverseOrderQueryable = noPaginationNoOrderQueryable.Skip((int)realSkip).Take((int)realSkip+take).OrderWithExpression(new List<PropertyOrder>()
|
||||
{
|
||||
new PropertyOrder( _primaryOrder.PropertyExpression,!_primaryOrder.IsAsc)
|
||||
});
|
||||
var enumeratorTasks = tableResult.Select(routeResult =>
|
||||
{
|
||||
var newQueryable = CreateAsyncExecuteQueryable(reverseOrderQueryable,routeResult);
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var asyncEnumerator = await DoGetAsyncEnumerator(newQueryable);
|
||||
return new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}).ToArray();
|
||||
|
||||
var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException();
|
||||
return streamEnumerators;
|
||||
}
|
||||
|
||||
private IQueryable<TEntity> CreateAsyncExecuteQueryable(IQueryable<TEntity> reverseOrderQueryable, RouteResult routeResult)
|
||||
{
|
||||
var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
|
||||
DbContextQueryStore.TryAdd(routeResult, shardingDbContext);
|
||||
var newQueryable = (IQueryable<TEntity>)reverseOrderQueryable
|
||||
.ReplaceDbContextQueryable(shardingDbContext);
|
||||
return newQueryable;
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
|
||||
{
|
||||
var doGetStreamMergeAsyncEnumerator = DoGetStreamMergeAsyncEnumerator(streamsAsyncEnumerators);
|
||||
return new InMemoryReverseStreamMergeAsyncEnumerator<TEntity>(doGetStreamMergeAsyncEnumerator);
|
||||
}
|
||||
|
||||
private IStreamMergeAsyncEnumerator<TEntity> DoGetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
|
||||
{
|
||||
if (StreamMergeContext.IsPaginationQuery())
|
||||
return new PaginationStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
if (StreamMergeContext.HasGroupQuery())
|
||||
return new MultiAggregateOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Base;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/2 16:29:06
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SequenceEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
|
||||
{
|
||||
private readonly PaginationConfig _orderPaginationConfig;
|
||||
private readonly ICollection<RouteQueryResult<long>> _routeQueryResults;
|
||||
private readonly bool _isAsc;
|
||||
public SequenceEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext, PaginationConfig orderPaginationConfig, ICollection<RouteQueryResult<long>> routeQueryResults, bool isAsc) : base(streamMergeContext)
|
||||
{
|
||||
_orderPaginationConfig = orderPaginationConfig;
|
||||
_routeQueryResults = routeQueryResults;
|
||||
_isAsc = isAsc;
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
|
||||
{
|
||||
var noPaginationQueryable = StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake();
|
||||
var skip = StreamMergeContext.Skip.GetValueOrDefault();
|
||||
if (skip < 0)
|
||||
throw new ShardingCoreException("skip must ge 0");
|
||||
|
||||
var take = StreamMergeContext.Take;
|
||||
if (take.HasValue && take.Value <= 0)
|
||||
throw new ShardingCoreException("take must gt 0");
|
||||
|
||||
var sortRouteResults = _routeQueryResults.Select(o => new
|
||||
{
|
||||
Tail = o.RouteResult.ReplaceTables.First().Tail,
|
||||
RouteQueryResult = o
|
||||
}).OrderByIf(o => o.Tail, _isAsc, _orderPaginationConfig.TailComparer)
|
||||
.OrderByDescendingIf(o => o.Tail, !_isAsc, _orderPaginationConfig.TailComparer).ToList();
|
||||
|
||||
var sequenceResults = new SequencePaginationList(sortRouteResults.Select(o => o.RouteQueryResult)).Skip(skip).Take(take).ToList();
|
||||
|
||||
var enumeratorTasks = sequenceResults.Select(sequenceResult =>
|
||||
{
|
||||
var newQueryable = CreateAsyncExecuteQueryable(noPaginationQueryable, sequenceResult);
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var asyncEnumerator = await DoGetAsyncEnumerator(newQueryable);
|
||||
return new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}).ToArray();
|
||||
|
||||
var streamEnumerators = Task.WhenAll(enumeratorTasks).WaitAndUnwrapException();
|
||||
return streamEnumerators;
|
||||
}
|
||||
|
||||
private IQueryable<TEntity> CreateAsyncExecuteQueryable(IQueryable<TEntity> noPaginationQueryable, SequenceResult sequenceResult)
|
||||
{
|
||||
var shardingDbContext = StreamMergeContext.CreateDbContext(sequenceResult.RouteResult);
|
||||
DbContextQueryStore.TryAdd(sequenceResult.RouteResult, shardingDbContext);
|
||||
var newQueryable = (IQueryable<TEntity>)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take))
|
||||
.ReplaceDbContextQueryable(shardingDbContext);
|
||||
return newQueryable;
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
|
||||
{
|
||||
if (StreamMergeContext.HasGroupQuery())
|
||||
return new MultiAggregateOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Thursday, 02 September 2021 20:58:10
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SingleQueryEnumeratorAsyncStreamMergeEngine<TEntity> : AbstractEnumeratorAsyncStreamMergeEngine<TEntity>
|
||||
{
|
||||
public SingleQueryEnumeratorAsyncStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext) : base(streamMergeContext)
|
||||
{
|
||||
}
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators()
|
||||
{
|
||||
var routeResult = StreamMergeContext.RouteResults.First();
|
||||
var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
|
||||
DbContextQueryStore.TryAdd(routeResult, shardingDbContext);
|
||||
var newQueryable = (IQueryable<TEntity>) StreamMergeContext.GetOriginalQueryable().ReplaceDbContextQueryable(shardingDbContext);
|
||||
|
||||
var asyncEnumerator = DoGetAsyncEnumerator(newQueryable).WaitAndUnwrapException();
|
||||
return new[] {new StreamMergeAsyncEnumerator<TEntity>(asyncEnumerator)};
|
||||
}
|
||||
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators)
|
||||
{
|
||||
return new MultiOrderStreamMergeAsyncEnumerator<TEntity>(StreamMergeContext, streamsAsyncEnumerators);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
|
||||
|
@ -28,20 +29,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override TResult MergeResult<TResult>()
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<TResult>)queryable).First());
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
return q.OrderWithExpression(streamMergeContext.Orders).First();
|
||||
|
||||
return q.First();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
|
||||
}
|
||||
|
||||
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).FirstAsync(cancellationToken), cancellationToken);
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
|
|
|
@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
|
@ -31,20 +32,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override TResult MergeResult<TResult>()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).FirstOrDefault());
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
return q.OrderWithExpression(streamMergeContext.Orders).FirstOrDefault();
|
||||
|
||||
return q.FirstOrDefault();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
|
||||
}
|
||||
|
||||
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).FirstOrDefaultAsync(cancellationToken), cancellationToken);
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
|
||||
|
@ -28,21 +29,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override TResult MergeResult<TResult>()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).Last());
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
return q.OrderWithExpression(streamMergeContext.Orders).Last();
|
||||
|
||||
return q.Last();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
|
||||
}
|
||||
|
||||
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).LastAsync(cancellationToken), cancellationToken);
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
|
||||
|
@ -28,20 +29,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override TResult MergeResult<TResult>()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).LastOrDefault());
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
return q.OrderWithExpression(streamMergeContext.Orders).LastOrDefault();
|
||||
|
||||
return q.LastOrDefault();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
|
||||
}
|
||||
|
||||
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).LastOrDefaultAsync(cancellationToken), cancellationToken);
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
|
|
|
@ -7,7 +7,9 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
|
@ -24,16 +26,15 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
*/
|
||||
public class LongCountAsyncInMemoryMergeEngine<TEntity> : AbstractEnsureMethodCallWhereInMemoryAsyncMergeEngine<TEntity,long>
|
||||
{
|
||||
private readonly IShardingPageManager _shardingPageManager;
|
||||
public LongCountAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
|
||||
{
|
||||
_shardingPageManager= ShardingContainer.GetService<IShardingPageManager>();
|
||||
}
|
||||
|
||||
public override long MergeResult()
|
||||
{
|
||||
|
||||
var result = base.Execute( queryable => ((IQueryable<TEntity>)queryable).LongCount());
|
||||
|
||||
return result.Sum();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync());
|
||||
}
|
||||
|
||||
public override async Task<long> MergeResultAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
|
@ -41,7 +42,15 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TEntity>)queryable).LongCountAsync(cancellationToken), cancellationToken);
|
||||
|
||||
return result.Sum();
|
||||
if (_shardingPageManager.Current != null)
|
||||
{
|
||||
foreach (var routeQueryResult in result)
|
||||
{
|
||||
_shardingPageManager.Current.RouteQueryResults.Add(routeQueryResult);
|
||||
}
|
||||
}
|
||||
|
||||
return result.Sum(o=>o.QueryResult);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/9/1 13:13:17
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class RouteQueryResult<TResult>
|
||||
{
|
||||
public RouteResult RouteResult { get; }
|
||||
public TResult QueryResult { get; }
|
||||
|
||||
public RouteQueryResult(RouteResult routeResult,TResult queryResult)
|
||||
{
|
||||
RouteResult = routeResult;
|
||||
QueryResult = queryResult;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
|
||||
|
@ -28,20 +29,13 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override TResult MergeResult<TResult>()
|
||||
{
|
||||
var result = base.Execute( queryable => ((IQueryable<TResult>)queryable).Single());
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
return q.OrderWithExpression(streamMergeContext.Orders).Single();
|
||||
|
||||
return q.Single();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
|
||||
}
|
||||
|
||||
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).SingleAsync(cancellationToken), cancellationToken);
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericExpressionMergeEngines;
|
||||
|
@ -28,20 +29,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
|
||||
public override TResult MergeResult<TResult>()
|
||||
{
|
||||
var result = base.Execute(queryable => ((IQueryable<TResult>)queryable).SingleOrDefault());
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
return q.OrderWithExpression(streamMergeContext.Orders).SingleOrDefault();
|
||||
|
||||
return q.SingleOrDefault();
|
||||
return AsyncHelper.RunSync(() => MergeResultAsync<TResult>());
|
||||
}
|
||||
|
||||
public override async Task<TResult> MergeResultAsync<TResult>(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var result = await base.ExecuteAsync( queryable => ((IQueryable<TResult>)queryable).SingleOrDefaultAsync(cancellationToken), cancellationToken);
|
||||
var q = result.Where(o => o != null).AsQueryable();
|
||||
var q = result.Where(o => o != null&&o.QueryResult!=null).Select(o=>o.QueryResult).AsQueryable();
|
||||
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
if (streamMergeContext.Orders.Any())
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
|
||||
namespace ShardingCore.Core.Internal.Visitors
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace ShardingCore
|
|||
/// </summary>
|
||||
/// <param name="total">总记录数。</param>
|
||||
/// <param name="data">当前页面的数据。</param>
|
||||
public ShardingPagedResult(List<T> data, int total)
|
||||
public ShardingPagedResult(List<T> data, long total)
|
||||
{
|
||||
this.Total = total;
|
||||
this.Data = data;
|
||||
|
@ -26,7 +26,7 @@ namespace ShardingCore
|
|||
/// <summary>
|
||||
/// 获取或设置总记录数。
|
||||
/// </summary>
|
||||
public int Total { get; set; }
|
||||
public long Total { get; set; }
|
||||
/// <summary>
|
||||
/// 分页数据
|
||||
/// </summary>
|
||||
|
|
Loading…
Reference in New Issue