From 8d4066433c510eed0ca060068ba3845a5518d76a Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Wed, 8 Nov 2023 09:26:47 +0800 Subject: [PATCH] =?UTF-8?q?[#255]=E4=BF=AE=E5=A4=8DEF.Property(o,property)?= =?UTF-8?q?=E7=9A=84=E6=8E=92=E5=BA=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/WeatherForecastController.cs | 50 +++++++++++++++++++ samples/Sample.MySql/Program.cs | 2 + .../Shardings/SysUserLogByMonthRoute.cs | 10 ++-- samples/Sample.MySql/Startup.cs | 1 + .../EFCores/EFCore7x/ShardingStateManager.cs | 23 ++++++--- .../MergeContexts/QueryableRewriteEngine.cs | 3 +- .../Visitors/QueryableExtraDiscoverVisitor.cs | 42 ++++++++++++++-- 7 files changed, 111 insertions(+), 20 deletions(-) diff --git a/samples/Sample.MySql/Controllers/WeatherForecastController.cs b/samples/Sample.MySql/Controllers/WeatherForecastController.cs index 8f2d3966..da639dfd 100644 --- a/samples/Sample.MySql/Controllers/WeatherForecastController.cs +++ b/samples/Sample.MySql/Controllers/WeatherForecastController.cs @@ -1,6 +1,8 @@ using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; +using MySqlConnector; using Sample.MySql.DbContexts; using Sample.MySql.Domain.Entities; using Sample.MySql.multi; @@ -453,6 +455,34 @@ namespace Sample.MySql.Controllers return Ok(); } + [HttpGet] + public async Task Get17() + { + var sysUserMods = await _defaultTableDbContext.SysUserMod.AsNoTracking() + .Select(o => new SysUserMod() + { + Name = o.Name, + Age = o.Age + }).OrderBy(x => EF.Property(x, "Name")).ToListAsync(); + + // var sysUserMods1 = await _defaultTableDbContext.Set().FromSqlRaw("select * from SysUserMod where id='2'").ToListAsync(); + // var sysUserMods2 = await _defaultTableDbContext.Set().FromSqlRaw("select * from SysTest where id='2'").ToListAsync(); + return Ok(sysUserMods); + } + [HttpGet] + public async Task Get18() + { + var sysUserMods = await _defaultTableDbContext.SysUserMod.AsNoTracking().GroupBy(o => o.Age) + .Select(o=>new + { + Age=o.Key + }) + .CountAsync(); + + // var sysUserMods1 = await _defaultTableDbContext.Set().FromSqlRaw("select * from SysUserMod where id='2'").ToListAsync(); + // var sysUserMods2 = await _defaultTableDbContext.Set().FromSqlRaw("select * from SysTest where id='2'").ToListAsync(); + return Ok(sysUserMods); + } // public void batachSave() // { @@ -469,5 +499,25 @@ namespace Sample.MySql.Controllers // }); // } // } + + public void get11() + { + var mySqlConnection = new MySqlConnection("链接字符串"); + var dbContextOptions1 = new DbContextOptionsBuilder().UseMySql(mySqlConnection,new MySqlServerVersion(new Version()),b=> + { + b.EnableRetryOnFailure(10, TimeSpan.FromSeconds(10), null); + }).Options; + var dbContextOptions2 = new DbContextOptionsBuilder().UseMySql(mySqlConnection,new MySqlServerVersion(new Version())).Options; + var unShardingDbContext1 = new UnShardingDbContext(dbContextOptions1);//映射到202301模型 + var unShardingDbContext2 = new UnShardingDbContext(dbContextOptions2);//映射到202302模型 + // unShardingDbContext2.Database.CreateExecutionStrategy() + var dbContextTransaction = unShardingDbContext1.Database.BeginTransaction(); + unShardingDbContext2.Database.UseTransaction(dbContextTransaction.GetDbTransaction()); + //unShardingDbContext1.add() + //unShardingDbContext2.add() + unShardingDbContext1.SaveChanges(); + unShardingDbContext2.SaveChanges(); + dbContextTransaction.Commit(); + } } } diff --git a/samples/Sample.MySql/Program.cs b/samples/Sample.MySql/Program.cs index b7b33031..a5b5e9a4 100644 --- a/samples/Sample.MySql/Program.cs +++ b/samples/Sample.MySql/Program.cs @@ -13,6 +13,8 @@ namespace Sample.MySql { public static void Main(string[] args) { + var id = Guid.NewGuid().ToString("n"); + Console.WriteLine(id); CreateHostBuilder(args).Build().Run(); } diff --git a/samples/Sample.MySql/Shardings/SysUserLogByMonthRoute.cs b/samples/Sample.MySql/Shardings/SysUserLogByMonthRoute.cs index 1581bd4e..1cf9c401 100644 --- a/samples/Sample.MySql/Shardings/SysUserLogByMonthRoute.cs +++ b/samples/Sample.MySql/Shardings/SysUserLogByMonthRoute.cs @@ -57,13 +57,11 @@ namespace Sample.MySql.Shardings protected override List AfterShardingRouteUnitFilter(DataSourceRouteResult dataSourceRouteResult, List shardingRouteUnits) { Console.WriteLine("AfterShardingRouteUnitFilter:"+shardingRouteUnits.Count); + if (shardingRouteUnits.Count > 10)//如果本次命中表过多 + { + return shardingRouteUnits.Take(10).ToList();//自己排序截断选择最新的10张自己加orderBy + } return base.AfterShardingRouteUnitFilter(dataSourceRouteResult, shardingRouteUnits); } - - public override Func GetRouteFilter(object shardingKey, ShardingOperatorEnum shardingOperator, string shardingPropertyName) - { - Console.WriteLine(1); - return base.GetRouteFilter(shardingKey, shardingOperator, shardingPropertyName); - } } } diff --git a/samples/Sample.MySql/Startup.cs b/samples/Sample.MySql/Startup.cs index ad5314e2..b357ca9d 100644 --- a/samples/Sample.MySql/Startup.cs +++ b/samples/Sample.MySql/Startup.cs @@ -130,6 +130,7 @@ namespace Sample.MySql // o.UseEntityFrameworkCoreProxies = true; o.ThrowIfQueryRouteNotMatch = false; o.AutoUseWriteConnectionStringAfterWriteDb = true; + o.MaxQueryConnectionsLimit = 10; o.UseExecutorDbContextConfigure(op => { diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs index 6f968cc3..24dd7601 100644 --- a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs +++ b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs @@ -15,7 +15,7 @@ using ShardingCore.Sharding.Abstractions; namespace ShardingCore.EFCores { - public class ShardingStateManager:StateManager + public class ShardingStateManager : StateManager { private readonly IShardingDbContext _currentShardingDbContext; @@ -41,7 +41,8 @@ namespace ShardingCore.EFCores return stateManager.GetOrCreateEntry(entity, findEntityType); } - public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) + public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, + in ValueBuffer valueBuffer) { throw new ShardingCoreNotImplementedException(); } @@ -51,7 +52,8 @@ namespace ShardingCore.EFCores throw new ShardingCoreNotImplementedException(); } - public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) + public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, + bool throwOnTypeMismatch = true) { throw new ShardingCoreNotImplementedException(); } @@ -61,7 +63,8 @@ namespace ShardingCore.EFCores //ApplyShardingConcepts(); int i = 0; //如果是内部开的事务就内部自己消化 - if (Context.Database.AutoTransactionsEnabled&&Context.Database.CurrentTransaction==null&&_currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + if (Context.Database.AutoTransactionsEnabled && Context.Database.CurrentTransaction == null && + _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) { using (var tran = Context.Database.BeginTransaction()) { @@ -77,22 +80,26 @@ namespace ShardingCore.EFCores return i; } - public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) + public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, + CancellationToken cancellationToken = new CancellationToken()) { //ApplyShardingConcepts(); int i = 0; //如果是内部开的事务就内部自己消化 - if (Context.Database.AutoTransactionsEnabled && Context.Database.CurrentTransaction==null && _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + if (Context.Database.AutoTransactionsEnabled && Context.Database.CurrentTransaction == null && + _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) { using (var tran = await Context.Database.BeginTransactionAsync(cancellationToken)) { - i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + i = await _currentShardingDbContext.GetShardingExecutor() + .SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); await tran.CommitAsync(cancellationToken); } } else { - i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + i = await _currentShardingDbContext.GetShardingExecutor() + .SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); } diff --git a/src/ShardingCore/Sharding/MergeContexts/QueryableRewriteEngine.cs b/src/ShardingCore/Sharding/MergeContexts/QueryableRewriteEngine.cs index 464f1988..9d6299aa 100644 --- a/src/ShardingCore/Sharding/MergeContexts/QueryableRewriteEngine.cs +++ b/src/ShardingCore/Sharding/MergeContexts/QueryableRewriteEngine.cs @@ -59,7 +59,7 @@ namespace ShardingCore.Sharding.MergeContexts var orders = orderByContext.PropertyOrders; var combineQueryable = mergeQueryCompilerContext.GetQueryCombineResult().GetCombineQueryable(); - + //去除分页,获取前Take+Skip数量 var reWriteQueryable = combineQueryable; if (take.HasValue || skip.HasValue) @@ -86,6 +86,7 @@ namespace ShardingCore.Sharding.MergeContexts //group字段不可以为空 var selectGroupKeyProperties = selectContext.SelectProperties.Where(o => !(o is SelectAggregateProperty)).ToArray(); + if (selectGroupKeyProperties.IsEmpty()) { throw new ShardingCoreInvalidOperationException( diff --git a/src/ShardingCore/Sharding/Visitors/QueryableExtraDiscoverVisitor.cs b/src/ShardingCore/Sharding/Visitors/QueryableExtraDiscoverVisitor.cs index 125c8e2b..6e0ab98b 100644 --- a/src/ShardingCore/Sharding/Visitors/QueryableExtraDiscoverVisitor.cs +++ b/src/ShardingCore/Sharding/Visitors/QueryableExtraDiscoverVisitor.cs @@ -86,15 +86,47 @@ namespace ShardingCore.Core.Internal.Visitors expression = orderMemberConvertExpression; } } - if (expression == null) - throw new NotSupportedException("sharding order not support "); + + Type orderOwnerType = null; List properties = new List(); - GetPropertyInfo(properties, expression); + if (expression != null) + { + GetPropertyInfo(properties, expression); + orderOwnerType = expression.Member.DeclaringType; + } + else + { + if(orderbody.NodeType == ExpressionType.Call && orderbody is MethodCallExpression methodCallExpression) + { + if (methodCallExpression.Method.DeclaringType == typeof(Microsoft.EntityFrameworkCore.EF)) + { + if (methodCallExpression.Arguments.Count != 2) + { + throw new NotSupportedException("sharding order EF.Property(o,property) not support,arguments count != 2"); + } + orderOwnerType = methodCallExpression.Arguments[0].Type; + if (methodCallExpression.Arguments[1] is ConstantExpression propertyConstantExpression) + { + properties.Add(propertyConstantExpression.Value.ToString()); + } + else + { + throw new NotSupportedException("sharding order EF.Property(o,property) not support,arguments[1] is not ConstantExpression"); + } + } + } + + if (properties.Count == 0) + { + throw new NotSupportedException("sharding order not support "); + } + } + if (!properties.Any()) throw new NotSupportedException("sharding order only support property expression"); properties.Reverse(); - var propertyExpression = string.Join(".", properties); - _orderByContext.PropertyOrders.AddFirst(new PropertyOrder(propertyExpression, method.Name == nameof(Queryable.OrderBy) || method.Name == nameof(Queryable.ThenBy), expression.Member.DeclaringType)); + var propertyExpression =properties.Count==1?properties[0]: string.Join(".", properties); + _orderByContext.PropertyOrders.AddFirst(new PropertyOrder(propertyExpression, method.Name == nameof(Queryable.OrderBy) || method.Name == nameof(Queryable.ThenBy), orderOwnerType)); } }