From 062f823bbfccae49af40596ddfa0fcf9fd3a74a4 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Thu, 28 Apr 2022 16:31:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8A=A8=E6=80=81=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=A1=A8=E5=90=8E=E7=BC=80=E5=89=8D=E5=90=8E=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E5=BB=B6=E8=BF=9F=E7=9A=84=E6=83=85=E5=86=B5=E4=B8=8B?= =?UTF-8?q?=E5=87=BA=E7=8E=B0=E7=9A=84bug=EF=BC=8C=E5=8F=91=E5=B8=83x.4.2.?= =?UTF-8?q?12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nuget-publish.bat | 8 +-- .../Controllers/ValuesController.cs | 2 +- .../SysUserSalaryVirtualTableRoute.cs | 2 +- .../Startup.cs | 31 +++++------ .../OrderVirtualDataSourceRoute.cs | 5 +- .../OrderHashRangeVirtualTableRoute.cs | 2 +- .../EFCores/ShardingModelCustomizer.cs | 4 +- .../AverageAsyncInMemoryMergeEngine.cs | 55 ++++++++++++++++++- ...rdingEntityFrameworkQueryableExtensions.cs | 43 +++++++++++++++ .../QueryCompilerContextFactory.cs | 13 ++--- 10 files changed, 125 insertions(+), 40 deletions(-) diff --git a/nuget-publish.bat b/nuget-publish.bat index f48de433..7c48f951 100644 --- a/nuget-publish.bat +++ b/nuget-publish.bat @@ -1,9 +1,9 @@ :start ::定义版本 -set EFCORE2=2.4.2.11 -set EFCORE3=3.4.2.11 -set EFCORE5=5.4.2.11 -set EFCORE6=6.4.2.11 +set EFCORE2=2.4.2.12 +set EFCORE3=3.4.2.12 +set EFCORE5=5.4.2.12 +set EFCORE6=6.4.2.12 ::删除所有bin与obj下的文件 @echo off diff --git a/samples/Sample.SqlServer/Controllers/ValuesController.cs b/samples/Sample.SqlServer/Controllers/ValuesController.cs index 55508ff6..dec7b4fc 100644 --- a/samples/Sample.SqlServer/Controllers/ValuesController.cs +++ b/samples/Sample.SqlServer/Controllers/ValuesController.cs @@ -166,7 +166,7 @@ namespace Sample.SqlServer.Controllers .Union(_defaultTableDbContext.Set().Select(o => new UnionUserId() { UserId = o.UserId })).UseUnionAllMerge().CountAsync(); var hashSet = unionUserIds.Select(o => o.UserId).ToHashSet(); var hashSetCount = hashSet.Count; - + var averageAsync = await _defaultTableDbContext.Set().Where(o => o.Age != 19).AverageAsync(o => o.Age); return Ok(); diff --git a/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs b/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs index c665e51e..1629fc03 100644 --- a/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs +++ b/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs @@ -43,7 +43,7 @@ namespace Sample.SqlServer.Shardings public override void Configure(EntityMetadataTableBuilder builder) { - + } protected string TimeFormatToTail(int time) diff --git a/samples/Sample.SqlServerShardingDataSource/Startup.cs b/samples/Sample.SqlServerShardingDataSource/Startup.cs index 61d9f6e8..e9d3c863 100644 --- a/samples/Sample.SqlServerShardingDataSource/Startup.cs +++ b/samples/Sample.SqlServerShardingDataSource/Startup.cs @@ -1,3 +1,4 @@ +using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; @@ -8,6 +9,8 @@ using Microsoft.Extensions.Logging; using Sample.SqlServerShardingDataSource.VirtualRoutes; using ShardingCore; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using ShardingCore.TableExists; namespace Sample.SqlServerShardingDataSource @@ -34,8 +37,8 @@ namespace Sample.SqlServerShardingDataSource services.AddShardingDbContext() .AddEntityConfig(o => { - o.CreateShardingTableOnStart = true; - o.EnsureCreatedWithOutShardingTable = true; + o.CreateShardingTableOnStart = false; + o.EnsureCreatedWithOutShardingTable = false; o.AddShardingDataSourceRoute(); o.AddShardingDataSourceRoute(); }) @@ -51,21 +54,14 @@ namespace Sample.SqlServerShardingDataSource builder.UseSqlServer(connection).UseLoggerFactory(efLogger); }); op.ReplaceTableEnsureManager(sp => new SqlServerTableEnsureManager()); - op.AddDefaultDataSource("A", - "Data Source=localhost;Initial Catalog=EFCoreShardingDataSourceDBA;Integrated Security=True;"); + op.AddDefaultDataSource("00", + "Data Source=localhost;Initial Catalog=EFCoreShardingDataSourceOnly00;Integrated Security=True;"); op.AddExtraDataSource(sp => { - return new Dictionary() - { - { - "B", - "Data Source=localhost;Initial Catalog=EFCoreShardingDataSourceDBB;Integrated Security=True;" - }, - { - "C", - "Data Source=localhost;Initial Catalog=EFCoreShardingDataSourceDBC;Integrated Security=True;" - }, - }; + return Enumerable.Range(1, 100).Select(o => (o % 100).ToString().PadLeft(2, '0')).ToList() + .ToDictionary(o => o, + o => + $"Data Source=localhost;Initial Catalog=EFCoreShardingDataSourceOnly{o};Integrated Security=True;"); }); }).EnsureConfig(); } @@ -78,7 +74,10 @@ namespace Sample.SqlServerShardingDataSource app.UseDeveloperExceptionPage(); } + Stopwatch sp=Stopwatch.StartNew(); app.UseShardingCore(); + sp.Stop(); + Console.WriteLine("ʱ"+sp.ElapsedMilliseconds); app.UseRouting(); app.UseAuthorization(); @@ -87,7 +86,7 @@ namespace Sample.SqlServerShardingDataSource { endpoints.MapControllers(); }); - app.InitSeed(); + //app.InitSeed(); } } } diff --git a/samples/Sample.SqlServerShardingDataSource/VirtualRoutes/OrderVirtualDataSourceRoute.cs b/samples/Sample.SqlServerShardingDataSource/VirtualRoutes/OrderVirtualDataSourceRoute.cs index 0f552543..31798d0f 100644 --- a/samples/Sample.SqlServerShardingDataSource/VirtualRoutes/OrderVirtualDataSourceRoute.cs +++ b/samples/Sample.SqlServerShardingDataSource/VirtualRoutes/OrderVirtualDataSourceRoute.cs @@ -11,10 +11,7 @@ namespace Sample.SqlServerShardingDataSource.VirtualRoutes { public class OrderVirtualDataSourceRoute : AbstractShardingOperatorVirtualDataSourceRoute { - private readonly List _dataSources = new List() - { - "A", "B", "C" - }; + private readonly List _dataSources = Enumerable.Range(0,100).Select(o=>(o % 100).ToString().PadLeft(2,'0')).ToList(); //我们设置区域就是数据库 public override string ShardingKeyToDataSourceName(object shardingKey) { diff --git a/samples/Sample.SqlServerShardingTable/VirtualRoutes/OrderHashRangeVirtualTableRoute.cs b/samples/Sample.SqlServerShardingTable/VirtualRoutes/OrderHashRangeVirtualTableRoute.cs index 9f994dbc..7d4994ec 100644 --- a/samples/Sample.SqlServerShardingTable/VirtualRoutes/OrderHashRangeVirtualTableRoute.cs +++ b/samples/Sample.SqlServerShardingTable/VirtualRoutes/OrderHashRangeVirtualTableRoute.cs @@ -17,7 +17,7 @@ namespace Sample.SqlServerShardingTable.VirtualRoutes public override string ShardingKeyToTail(object shardingKey) { - var stringHashCode = ShardingCoreHelper.GetStringHashCode("123"); + var stringHashCode = ShardingCoreHelper.GetStringHashCode(shardingKey.ToString()); var hashCode = stringHashCode % 10000; if (hashCode >= 0 && hashCode <= 3000) { diff --git a/src/ShardingCore/EFCores/ShardingModelCustomizer.cs b/src/ShardingCore/EFCores/ShardingModelCustomizer.cs index 21e57bb2..63989d0d 100644 --- a/src/ShardingCore/EFCores/ShardingModelCustomizer.cs +++ b/src/ShardingCore/EFCores/ShardingModelCustomizer.cs @@ -43,11 +43,9 @@ namespace ShardingCore.EFCores { var singleQueryRouteTail = (ISingleQueryRouteTail) shardingTableDbContext.RouteTail; var tail = singleQueryRouteTail.GetTail(); - var virtualTableManager = ShardingContainer.GetService>(); - var typeMap = virtualTableManager.GetAllVirtualTables().Where(o => o.GetTableAllTails().Contains(tail)).Select(o => o.EntityMetadata.EntityType).ToHashSet(); //设置分表 - var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => _entityMetadataManager.IsShardingTable(o.ClrType) && typeMap.Contains(o.ClrType)).ToArray(); + var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => _entityMetadataManager.IsShardingTable(o.ClrType)).ToArray(); foreach (var entityType in mutableEntityTypes) { MappingToTable(entityType.ClrType, modelBuilder, tail); diff --git a/src/ShardingCore/Sharding/MergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs index c5b90ce1..4f00be41 100644 --- a/src/ShardingCore/Sharding/MergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/AggregateMergeEngines/AverageAsyncInMemoryMergeEngine.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -37,11 +38,63 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines return default; } - var sum = await GetSumAsync(queryable,cancellationToken); + var sum = await GetSumAsync(queryable, cancellationToken); return new AverageResult(sum, count); }, cancellationToken)).Where(o => o.QueryResult != null).ToList(); + // return (await base.ExecuteAsync( + // async queryable => + // { + // var count = 0L; + // T sum = default; + // //MethodInfo sumMethod = typeof(Queryable).GetMethods().First( + // // m => m.Name == nameof(Queryable.Sum) + // // && m.ReturnType == typeof(T) + // // && m.IsGenericMethod); + + // //var genericSumMethod = sumMethod.MakeGenericMethod(new[] { source.ElementType }); + // var newQueryable = ((IQueryable)queryable).Select(o=>(decimal?)(object)o); + //#if !EFCORE2 + // var r = await newQueryable.GroupBy(o=>1).Select(o=>new + // { + // C= o.LongCount(), + // //S = ShardingEntityFrameworkQueryableExtensions.Execute(ShardingQueryableMethods.GetSumWithoutSelector(typeof(T)), newQueryable, (Expression)null) + // S = o.Sum() + + // }).FirstOrDefaultAsync(cancellationToken); + // ////https://stackoverflow.com/questions/21143179/build-groupby-expression-tree-with-multiple-fields + // ////https://blog.wiseowls.co.nz/index.php/2021/05/13/ef-core-3-1-dynamic-groupby-clause/ + + + // ////https://blog.wiseowls.co.nz/index.php/2021/05/13/ef-core-3-1-dynamic-groupby-clause/ + // ////https://stackoverflow.com/questions/39728898/groupby-query-by-linq-expressions-and-lambdas + // // Expression.New( + // // Type.GetType("System.Tuple`" + fields.Length) + // // .MakeGenericType(fields.Select(studentType.GetProperty), + // // fields.Select(f => Expression.PropertyOrField(itemParam, f)) + // // ) + // // if (r != null) + // // { + // // count = r.C; + // // //sum = r.S; + // // } + + //#endif + //#if EFCORE2 + // count = await ((IQueryable)queryable).LongCountAsync(cancellationToken); + // if (count <= 0) + // { + // return default; + // } + + // sum = await GetSumAsync(queryable, cancellationToken); + //#endif + + // return new AverageResult(sum, count); + + // }, + // cancellationToken)).Where(o => o.QueryResult != null).ToList(); } private async Task GetSumAsync(IQueryable queryable, diff --git a/src/ShardingCore/Sharding/ShardingEntityFrameworkQueryableExtensions.cs b/src/ShardingCore/Sharding/ShardingEntityFrameworkQueryableExtensions.cs index 50fc44a1..d72d6bcf 100644 --- a/src/ShardingCore/Sharding/ShardingEntityFrameworkQueryableExtensions.cs +++ b/src/ShardingCore/Sharding/ShardingEntityFrameworkQueryableExtensions.cs @@ -55,6 +55,38 @@ namespace ShardingCore.Sharding CancellationToken cancellationToken1 = cancellationToken; return provider.ExecuteAsync((Expression)methodCallExpression, cancellationToken1); } + public static TResult Execute( + MethodInfo operatorMethodInfo, + IQueryable source, + Expression? expression) + { + if (!(source.Provider is IAsyncQueryProvider provider)) + throw new InvalidOperationException(CoreStrings.IQueryableProviderNotAsync); + if (operatorMethodInfo.IsGenericMethod) + { + MethodInfo methodInfo; + if (operatorMethodInfo.GetGenericArguments().Length != 2) + methodInfo = operatorMethodInfo.MakeGenericMethod(typeof(TSource)); + else + methodInfo = operatorMethodInfo.MakeGenericMethod(typeof(TSource), ((IEnumerable)typeof(TResult).GetGenericArguments()).Single()); + operatorMethodInfo = methodInfo; + } + MethodInfo method = operatorMethodInfo; + Expression[] expressionArray; + if (expression != null) + expressionArray = new Expression[2] + { + source.Expression, + expression + }; + else + expressionArray = new Expression[1] + { + source.Expression + }; + MethodCallExpression methodCallExpression = Expression.Call((Expression)null, method, expressionArray); + return provider.Execute((Expression)methodCallExpression); + } #endif @@ -74,6 +106,17 @@ namespace ShardingCore.Sharding CancellationToken cancellationToken1 = cancellationToken; return provider.ExecuteAsync((Expression) methodCallExpression, cancellationToken1); } + public static TResult Execute( + MethodInfo operatorMethodInfo, + IQueryable source) + { + if (!(source.Provider is IAsyncQueryProvider provider)) + throw new InvalidOperationException(CoreStrings.IQueryableProviderNotAsync); + if (operatorMethodInfo.IsGenericMethod) + operatorMethodInfo = operatorMethodInfo.MakeGenericMethod(typeof (TSource)); + MethodCallExpression methodCallExpression = Expression.Call((Expression) null, operatorMethodInfo, source.Expression); + return provider.Execute((Expression) methodCallExpression); + } #endif } } diff --git a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs index 41c31c19..29a12949 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; using ShardingCore.Exceptions; @@ -13,7 +6,9 @@ using ShardingCore.Extensions; using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.ShardingExecutors.Abstractions; using ShardingCore.Sharding.ShardingExecutors.QueryableCombines; -using ShardingCore.Sharding.Visitors; +using System; +using System.Linq; +using System.Linq.Expressions; namespace ShardingCore.Sharding.ShardingExecutors {