修复multi route bug 发布x.3.1.95

This commit is contained in:
xuejiaming 2021-12-30 17:35:22 +08:00
parent 6f3ce998e4
commit b90a240547
9 changed files with 85 additions and 32 deletions

View File

@ -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

View File

@ -30,6 +30,11 @@ namespace ShardingCore.Core.EntityMetadatas
return false;
return entityMetadata.IsMultiTableMapping;
}
public bool IsOnlyShardingTable(Type entityType)
{
return IsShardingTable(entityType) && !IsShardingDataSource(entityType);
}
/// <summary>
/// 对象是否是分库对象
/// </summary>
@ -41,6 +46,11 @@ namespace ShardingCore.Core.EntityMetadatas
return false;
return entityMetadata.IsMultiDataSourceMapping;
}
public bool IsOnlyShardingDataSource(Type entityType)
{
return IsShardingDataSource(entityType) && !IsShardingTable(entityType);
}
/// <summary>
/// 对象获取没有返回null
/// </summary>

View File

@ -21,12 +21,14 @@ namespace ShardingCore.Core.EntityMetadatas
/// <param name="entityType"></param>
/// <returns></returns>
bool IsShardingTable(Type entityType);
bool IsOnlyShardingTable(Type entityType);
/// <summary>
/// 是否分库
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
bool IsShardingDataSource(Type entityType);
bool IsOnlyShardingDataSource(Type entityType);
/// <summary>
/// 尝试获取
/// </summary>

View File

@ -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<IPhysicTable> ReplaceTables { get; }
public bool NoDifferentTail { get; }
public Type ShardingDbContextType { get; }
protected bool Equals(TableRouteResult other)
{

View File

@ -67,10 +67,14 @@ namespace ShardingCore.Extensions
return (IQueryable<T>) source.Provider.CreateQuery(expression);
}
internal static bool? GetIsNoTracking<T>(this IQueryable<T> 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;
}

View File

@ -25,5 +25,7 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
/// </summary>
/// <returns></returns>
bool CurrentQueryReadConnection();
bool IsQueryTrack();
}
}

View File

@ -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<IRouteTailFactory>();
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<IRouteTailFactory>();
var dbContext = GetShardingDbContext().GetDbContext(_dataSourceRouteResult.IntersectDataSources.First(), !IsQueryTrack() || CurrentQueryReadConnection(), routeTailFactory.Create(_tableRouteResults.First()));
_queryCompilerExecutor = new QueryCompilerExecutor(dbContext, GetQueryExpression());
}
}
}
return _queryCompilerExecutor;
}
/// <summary>
/// 既不可以跨库也不可以跨表,所有的分表都必须是相同后缀才可以
/// </summary>
/// <returns></returns>
private bool IsSingleDbContextNativeQuery()
{
return !_isCrossDataSource && !_isCrossTable && (!IsQueryTrack() || OnlyShardingDataSourceOrNoDifferentTail());
}
/// <summary>
/// 不存在分表或者分了但是都是一样的tail并且没有不分表的对象
/// </summary>
/// <returns></returns>
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()

View File

@ -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)

View File

@ -55,10 +55,6 @@ namespace ShardingCore.Sharding
/// </summary>
public ISet<Type> QueryEntities { get; }
/// <summary>
/// 本次查询是否包含notracking
/// </summary>
public bool? IsNoTracking { get; }
/// <summary>
/// 本次查询跨库
/// </summary>
public bool IsCrossDataSource { get; }
@ -91,7 +87,6 @@ namespace ShardingCore.Sharding
Skip = reWriteResult.Skip;
Take = reWriteResult.Take;
Orders = reWriteResult.Orders ?? Enumerable.Empty<PropertyOrder>();
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()