diff --git a/nuget-publish.bat b/nuget-publish.bat index 40b754cc..0dbde81a 100644 --- a/nuget-publish.bat +++ b/nuget-publish.bat @@ -1,9 +1,9 @@ :start ::定义版本 -set EFCORE2=2.3.1.94 -set EFCORE3=3.3.1.94 -set EFCORE5=5.3.1.94 -set EFCORE6=6.3.1.94 +set EFCORE2=2.3.1.95 +set EFCORE3=3.3.1.95 +set EFCORE5=5.3.1.95 +set EFCORE6=6.3.1.95 ::删除所有bin与obj下的文件 @echo off diff --git a/src/ShardingCore/Core/EntityMetadatas/DefaultEntityMetadataManager.cs b/src/ShardingCore/Core/EntityMetadatas/DefaultEntityMetadataManager.cs index 620b4057..bba20b2b 100644 --- a/src/ShardingCore/Core/EntityMetadatas/DefaultEntityMetadataManager.cs +++ b/src/ShardingCore/Core/EntityMetadatas/DefaultEntityMetadataManager.cs @@ -30,6 +30,11 @@ namespace ShardingCore.Core.EntityMetadatas return false; return entityMetadata.IsMultiTableMapping; } + public bool IsOnlyShardingTable(Type entityType) + { + return IsShardingTable(entityType) && !IsShardingDataSource(entityType); + } + /// /// 对象是否是分库对象 /// @@ -41,6 +46,11 @@ namespace ShardingCore.Core.EntityMetadatas return false; return entityMetadata.IsMultiDataSourceMapping; } + public bool IsOnlyShardingDataSource(Type entityType) + { + return IsShardingDataSource(entityType) && !IsShardingTable(entityType); + } + /// /// 对象获取没有返回null /// diff --git a/src/ShardingCore/Core/EntityMetadatas/IEntityMetadataManager.cs b/src/ShardingCore/Core/EntityMetadatas/IEntityMetadataManager.cs index f415b165..9afd445a 100644 --- a/src/ShardingCore/Core/EntityMetadatas/IEntityMetadataManager.cs +++ b/src/ShardingCore/Core/EntityMetadatas/IEntityMetadataManager.cs @@ -21,12 +21,14 @@ namespace ShardingCore.Core.EntityMetadatas /// /// bool IsShardingTable(Type entityType); + bool IsOnlyShardingTable(Type entityType); /// /// 是否分库 /// /// /// bool IsShardingDataSource(Type entityType); + bool IsOnlyShardingDataSource(Type entityType); /// /// 尝试获取 /// diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteResult.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteResult.cs index 8d08ddec..4311b4a4 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteResult.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/RoutingRuleEngine/TableRouteResult.cs @@ -2,10 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using ShardingCore.Core.PhysicTables; - -#if !EFCORE5 using ShardingCore.Extensions; -#endif namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine { @@ -21,9 +18,12 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine { ShardingDbContextType = shardingDbContextType; ReplaceTables = replaceTables.ToHashSet(); + NoDifferentTail = ReplaceTables.IsEmpty() || ReplaceTables.GroupBy(o => o.Tail).Count() == 1; } - + public ISet ReplaceTables { get; } + + public bool NoDifferentTail { get; } public Type ShardingDbContextType { get; } protected bool Equals(TableRouteResult other) { diff --git a/src/ShardingCore/Extensions/IShardingQueryableExtension.cs b/src/ShardingCore/Extensions/IShardingQueryableExtension.cs index 4fd1360b..9be29d1f 100644 --- a/src/ShardingCore/Extensions/IShardingQueryableExtension.cs +++ b/src/ShardingCore/Extensions/IShardingQueryableExtension.cs @@ -67,10 +67,14 @@ namespace ShardingCore.Extensions return (IQueryable) source.Provider.CreateQuery(expression); } - internal static bool? GetIsNoTracking(this IQueryable source) + internal static bool? GetIsNoTracking(this IQueryable source) + { + return GetIsNoTracking(source.Expression); + } + internal static bool? GetIsNoTracking(this Expression expression) { var queryableTrackingDiscoverVisitor = new QueryableTrackingDiscoverVisitor(); - queryableTrackingDiscoverVisitor.Visit(source.Expression); + queryableTrackingDiscoverVisitor.Visit(expression); return queryableTrackingDiscoverVisitor.IsNoTracking; } diff --git a/src/ShardingCore/Sharding/ShardingExecutors/Abstractions/IQueryCompilerContext.cs b/src/ShardingCore/Sharding/ShardingExecutors/Abstractions/IQueryCompilerContext.cs index 23440577..6876424f 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/Abstractions/IQueryCompilerContext.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/Abstractions/IQueryCompilerContext.cs @@ -25,5 +25,7 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions /// /// bool CurrentQueryReadConnection(); + + bool IsQueryTrack(); } } diff --git a/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs b/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs index fbae0290..4014e2b5 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs @@ -97,21 +97,53 @@ namespace ShardingCore.Sharding.ShardingExecutors return _queryCompilerContext.CurrentQueryReadConnection(); } + public bool IsQueryTrack() + { + return _queryCompilerContext.IsQueryTrack(); + } + + public QueryCompilerExecutor GetQueryCompilerExecutor() { if (!hasQueryCompilerExecutor.HasValue) { - hasQueryCompilerExecutor = !IsMergeQuery(); - if (hasQueryCompilerExecutor.Value) + if (_dataSourceRouteResult.IntersectDataSources.IsEmpty() || _tableRouteResults.IsEmpty()) { - var routeTailFactory = ShardingContainer.GetService(); - var dbContext = GetShardingDbContext().GetDbContext(_dataSourceRouteResult.IntersectDataSources.First(), CurrentQueryReadConnection(), routeTailFactory.Create(_tableRouteResults.First())); - _queryCompilerExecutor = new QueryCompilerExecutor(dbContext, GetQueryExpression()); + hasQueryCompilerExecutor = false; + } + else + { + hasQueryCompilerExecutor = IsSingleDbContextNativeQuery(); + if (hasQueryCompilerExecutor.Value) + { + var routeTailFactory = ShardingContainer.GetService(); + var dbContext = GetShardingDbContext().GetDbContext(_dataSourceRouteResult.IntersectDataSources.First(), !IsQueryTrack() || CurrentQueryReadConnection(), routeTailFactory.Create(_tableRouteResults.First())); + _queryCompilerExecutor = new QueryCompilerExecutor(dbContext, GetQueryExpression()); + } } } return _queryCompilerExecutor; } + /// + /// 既不可以跨库也不可以跨表,所有的分表都必须是相同后缀才可以 + /// + /// + private bool IsSingleDbContextNativeQuery() + { + return !_isCrossDataSource && !_isCrossTable && (!IsQueryTrack() || OnlyShardingDataSourceOrNoDifferentTail()); + } + /// + /// 不存在分表或者分了但是都是一样的tail并且没有不分表的对象 + /// + /// + private bool OnlyShardingDataSourceOrNoDifferentTail() + { + if (GetQueryEntities().All(o => GetEntityMetadataManager().IsOnlyShardingDataSource(o))) + return true; + var firstTableRouteResult = _tableRouteResults.First(); + return (firstTableRouteResult.NoDifferentTail && GetQueryEntities().All(o => GetEntityMetadataManager().IsShardingTable(o))); + } public QueryCombineResult GetQueryCombineResult() diff --git a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs index f4dd383a..41a45800 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs @@ -27,11 +27,13 @@ namespace ShardingCore.Sharding.ShardingExecutors private readonly IShardingConfigOption _shardingConfigOption; private QueryCompilerExecutor _queryCompilerExecutor; private bool? hasQueryCompilerExecutor; + private bool? _isNoTracking; private QueryCompilerContext( IShardingDbContext shardingDbContext, Expression queryExpression) { _shardingDbContextType = shardingDbContext.GetType(); _queryEntities = ShardingUtil.GetQueryEntitiesByExpression(queryExpression, _shardingDbContextType); + _isNoTracking = queryExpression.GetIsNoTracking(); _shardingDbContext = shardingDbContext; _queryExpression = queryExpression; _entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(_shardingDbContextType)); @@ -73,6 +75,23 @@ namespace ShardingCore.Sharding.ShardingExecutors { return _shardingConfigOption.UseReadWrite&&_shardingDbContext.CurrentIsReadWriteSeparation(); } + + public bool IsQueryTrack() + { + var shardingDbContext = (DbContext)_shardingDbContext; + if (!shardingDbContext.ChangeTracker.AutoDetectChangesEnabled) + return false; + if (_isNoTracking.HasValue) + { + return !_isNoTracking.Value; + } + else + { + return shardingDbContext.ChangeTracker.QueryTrackingBehavior == + QueryTrackingBehavior.TrackAll; + } + } + public QueryCompilerExecutor GetQueryCompilerExecutor() { if (!hasQueryCompilerExecutor.HasValue) diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index 532d9928..c70e42ed 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -55,10 +55,6 @@ namespace ShardingCore.Sharding /// public ISet QueryEntities { get; } /// - /// 本次查询是否包含notracking - /// - public bool? IsNoTracking { get; } - /// /// 本次查询跨库 /// public bool IsCrossDataSource { get; } @@ -91,7 +87,6 @@ namespace ShardingCore.Sharding Skip = reWriteResult.Skip; Take = reWriteResult.Take; Orders = reWriteResult.Orders ?? Enumerable.Empty(); - IsNoTracking = _source.GetIsNoTracking(); SelectContext = reWriteResult.SelectContext; GroupByContext = reWriteResult.GroupByContext; _reWriteSource = reWriteResult.ReWriteQueryable; @@ -248,18 +243,7 @@ namespace ShardingCore.Sharding } private bool QueryTrack() { - var shardingDbContext = (DbContext)_shardingDbContext; - if (!shardingDbContext.ChangeTracker.AutoDetectChangesEnabled) - return false; - if (IsNoTracking.HasValue) - { - return !IsNoTracking.Value; - } - else - { - return shardingDbContext.ChangeTracker.QueryTrackingBehavior == - QueryTrackingBehavior.TrackAll; - } + return MergeQueryCompilerContext.IsQueryTrack(); } public IShardingComparer GetShardingComparer()