修复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 :start
::定义版本 ::定义版本
set EFCORE2=2.3.1.94 set EFCORE2=2.3.1.95
set EFCORE3=3.3.1.94 set EFCORE3=3.3.1.95
set EFCORE5=5.3.1.94 set EFCORE5=5.3.1.95
set EFCORE6=6.3.1.94 set EFCORE6=6.3.1.95
::删除所有bin与obj下的文件 ::删除所有bin与obj下的文件
@echo off @echo off

View File

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

View File

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

View File

@ -2,10 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ShardingCore.Core.PhysicTables; using ShardingCore.Core.PhysicTables;
#if !EFCORE5
using ShardingCore.Extensions; using ShardingCore.Extensions;
#endif
namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
{ {
@ -21,9 +18,12 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
{ {
ShardingDbContextType = shardingDbContextType; ShardingDbContextType = shardingDbContextType;
ReplaceTables = replaceTables.ToHashSet(); ReplaceTables = replaceTables.ToHashSet();
NoDifferentTail = ReplaceTables.IsEmpty() || ReplaceTables.GroupBy(o => o.Tail).Count() == 1;
} }
public ISet<IPhysicTable> ReplaceTables { get; } public ISet<IPhysicTable> ReplaceTables { get; }
public bool NoDifferentTail { get; }
public Type ShardingDbContextType { get; } public Type ShardingDbContextType { get; }
protected bool Equals(TableRouteResult other) protected bool Equals(TableRouteResult other)
{ {

View File

@ -67,10 +67,14 @@ namespace ShardingCore.Extensions
return (IQueryable<T>) source.Provider.CreateQuery(expression); 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(); var queryableTrackingDiscoverVisitor = new QueryableTrackingDiscoverVisitor();
queryableTrackingDiscoverVisitor.Visit(source.Expression); queryableTrackingDiscoverVisitor.Visit(expression);
return queryableTrackingDiscoverVisitor.IsNoTracking; return queryableTrackingDiscoverVisitor.IsNoTracking;
} }

View File

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

View File

@ -97,21 +97,53 @@ namespace ShardingCore.Sharding.ShardingExecutors
return _queryCompilerContext.CurrentQueryReadConnection(); return _queryCompilerContext.CurrentQueryReadConnection();
} }
public bool IsQueryTrack()
{
return _queryCompilerContext.IsQueryTrack();
}
public QueryCompilerExecutor GetQueryCompilerExecutor() public QueryCompilerExecutor GetQueryCompilerExecutor()
{ {
if (!hasQueryCompilerExecutor.HasValue) if (!hasQueryCompilerExecutor.HasValue)
{ {
hasQueryCompilerExecutor = !IsMergeQuery(); if (_dataSourceRouteResult.IntersectDataSources.IsEmpty() || _tableRouteResults.IsEmpty())
{
hasQueryCompilerExecutor = false;
}
else
{
hasQueryCompilerExecutor = IsSingleDbContextNativeQuery();
if (hasQueryCompilerExecutor.Value) if (hasQueryCompilerExecutor.Value)
{ {
var routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>(); var routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
var dbContext = GetShardingDbContext().GetDbContext(_dataSourceRouteResult.IntersectDataSources.First(), CurrentQueryReadConnection(), routeTailFactory.Create(_tableRouteResults.First())); var dbContext = GetShardingDbContext().GetDbContext(_dataSourceRouteResult.IntersectDataSources.First(), !IsQueryTrack() || CurrentQueryReadConnection(), routeTailFactory.Create(_tableRouteResults.First()));
_queryCompilerExecutor = new QueryCompilerExecutor(dbContext, GetQueryExpression()); _queryCompilerExecutor = new QueryCompilerExecutor(dbContext, GetQueryExpression());
} }
} }
}
return _queryCompilerExecutor; 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() public QueryCombineResult GetQueryCombineResult()

View File

@ -27,11 +27,13 @@ namespace ShardingCore.Sharding.ShardingExecutors
private readonly IShardingConfigOption _shardingConfigOption; private readonly IShardingConfigOption _shardingConfigOption;
private QueryCompilerExecutor _queryCompilerExecutor; private QueryCompilerExecutor _queryCompilerExecutor;
private bool? hasQueryCompilerExecutor; private bool? hasQueryCompilerExecutor;
private bool? _isNoTracking;
private QueryCompilerContext( IShardingDbContext shardingDbContext, Expression queryExpression) private QueryCompilerContext( IShardingDbContext shardingDbContext, Expression queryExpression)
{ {
_shardingDbContextType = shardingDbContext.GetType(); _shardingDbContextType = shardingDbContext.GetType();
_queryEntities = ShardingUtil.GetQueryEntitiesByExpression(queryExpression, _shardingDbContextType); _queryEntities = ShardingUtil.GetQueryEntitiesByExpression(queryExpression, _shardingDbContextType);
_isNoTracking = queryExpression.GetIsNoTracking();
_shardingDbContext = shardingDbContext; _shardingDbContext = shardingDbContext;
_queryExpression = queryExpression; _queryExpression = queryExpression;
_entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(_shardingDbContextType)); _entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(_shardingDbContextType));
@ -73,6 +75,23 @@ namespace ShardingCore.Sharding.ShardingExecutors
{ {
return _shardingConfigOption.UseReadWrite&&_shardingDbContext.CurrentIsReadWriteSeparation(); 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() public QueryCompilerExecutor GetQueryCompilerExecutor()
{ {
if (!hasQueryCompilerExecutor.HasValue) if (!hasQueryCompilerExecutor.HasValue)

View File

@ -55,10 +55,6 @@ namespace ShardingCore.Sharding
/// </summary> /// </summary>
public ISet<Type> QueryEntities { get; } public ISet<Type> QueryEntities { get; }
/// <summary> /// <summary>
/// 本次查询是否包含notracking
/// </summary>
public bool? IsNoTracking { get; }
/// <summary>
/// 本次查询跨库 /// 本次查询跨库
/// </summary> /// </summary>
public bool IsCrossDataSource { get; } public bool IsCrossDataSource { get; }
@ -91,7 +87,6 @@ namespace ShardingCore.Sharding
Skip = reWriteResult.Skip; Skip = reWriteResult.Skip;
Take = reWriteResult.Take; Take = reWriteResult.Take;
Orders = reWriteResult.Orders ?? Enumerable.Empty<PropertyOrder>(); Orders = reWriteResult.Orders ?? Enumerable.Empty<PropertyOrder>();
IsNoTracking = _source.GetIsNoTracking();
SelectContext = reWriteResult.SelectContext; SelectContext = reWriteResult.SelectContext;
GroupByContext = reWriteResult.GroupByContext; GroupByContext = reWriteResult.GroupByContext;
_reWriteSource = reWriteResult.ReWriteQueryable; _reWriteSource = reWriteResult.ReWriteQueryable;
@ -248,18 +243,7 @@ namespace ShardingCore.Sharding
} }
private bool QueryTrack() private bool QueryTrack()
{ {
var shardingDbContext = (DbContext)_shardingDbContext; return MergeQueryCompilerContext.IsQueryTrack();
if (!shardingDbContext.ChangeTracker.AutoDetectChangesEnabled)
return false;
if (IsNoTracking.HasValue)
{
return !IsNoTracking.Value;
}
else
{
return shardingDbContext.ChangeTracker.QueryTrackingBehavior ==
QueryTrackingBehavior.TrackAll;
}
} }
public IShardingComparer GetShardingComparer() public IShardingComparer GetShardingComparer()