diff --git a/samples/Sample.SqlServer/Controllers/ValuesController.cs b/samples/Sample.SqlServer/Controllers/ValuesController.cs index 16091226..e0a91c9d 100644 --- a/samples/Sample.SqlServer/Controllers/ValuesController.cs +++ b/samples/Sample.SqlServer/Controllers/ValuesController.cs @@ -56,7 +56,7 @@ namespace Sample.SqlServer.Controllers userId = u.Id }; var listAsync = await sql.ToListAsync(); - var resultx112331tt = await _defaultTableDbContext.Set().CountAsync(); + var resultx112331tt = await _defaultTableDbContext.Set().AsNoTracking().CountAsync(); var resultx112331 = await _defaultTableDbContext.Set().CountAsync(); var resultx11233411 = _defaultTableDbContext.Set().Count(); var resultx11231 = await _defaultTableDbContext.Set().Where(o => o.Age == 198198).Select(o => o.Id).ContainsAsync("1981"); diff --git a/src/ShardingCore/Core/EntityMetadatas/EntityMetadataTableBuilder.cs b/src/ShardingCore/Core/EntityMetadatas/EntityMetadataTableBuilder.cs index b489ec86..d4d51104 100644 --- a/src/ShardingCore/Core/EntityMetadatas/EntityMetadataTableBuilder.cs +++ b/src/ShardingCore/Core/EntityMetadatas/EntityMetadataTableBuilder.cs @@ -49,7 +49,8 @@ namespace ShardingCore.Core.EntityMetadatas return this; } /// - /// 是否启动建表 + /// 是否启动的时候创建表,仅在启动时判断该属性,如果你是按时间分表的那么这个属性将不会在特定时间创建对应的表信息需要手动进行表创建和添加 + /// 当然您也可以使用系统默认的时间路由,通过重写AutoCreateByTime方法重写返回true来保证sharding_core开启定时任务并且已经集成自动创建表和库 /// /// /// diff --git a/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs b/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs index f660cfac..4b034989 100644 --- a/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs @@ -86,6 +86,9 @@ namespace ShardingCore.DIExtensions public bool? CreateShardingTableOnStart { get; set; } /// /// 是否自动追踪实体 + /// 譬如本次查询涉及到a1,a2,a3这三张表,会创建3个dbcontext进行查询,如果AutoTrackEntity=false那么针对被创建的dbcontext不会有任何变化,还是以追踪的形式查询 + /// 因为会同时创建3个dbcontext所以针对跨表查询完成后dbcontext会被回收,但是查询还是按原先的行为查询,所以如果不启用建议在查询的时候使用notracking + /// 如果AutoTrackEntity=true,那么被创建的三个dbcontext还是以原先的表现行为进行查询,在查询完成后会再次各自创建对应的dbcontext进行对象的追踪 /// public bool AutoTrackEntity { get; set; } diff --git a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs index 93a04da7..4cec8341 100644 --- a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs +++ b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs @@ -23,20 +23,11 @@ namespace ShardingCore.DbContexts { var routeTail=shardingDbContextOptions.RouteTail; - var dbContext = _shardingDbContextCreatorConfig.Creator(shardingDbContextOptions); + var dbContext = _shardingDbContextCreatorConfig.Creator(shardingDbContextOptions); if (dbContext is IShardingTableDbContext shardingTableDbContext) { shardingTableDbContext.RouteTail = routeTail; } - - //if (dbContext is IShardingDbContext shardingDbContext) - //{ - // shardingDbContext.ShardingUpgrade(); - //} - //else - //{ - // throw new ShardingCoreException($"{dbContext.GetType().FullName} should implements {nameof(IShardingDbContext)}"); - //} var dbContextModel = dbContext.Model; return dbContext; } diff --git a/src/ShardingCore/Extensions/IShardingQueryableExtension.cs b/src/ShardingCore/Extensions/IShardingQueryableExtension.cs index 33a1d1ce..dee139b2 100644 --- a/src/ShardingCore/Extensions/IShardingQueryableExtension.cs +++ b/src/ShardingCore/Extensions/IShardingQueryableExtension.cs @@ -78,10 +78,11 @@ namespace ShardingCore.Extensions /// /// 元数据源 /// 新数据源 + /// 是否是并行查询,是的话直接启用asnotracking /// - internal static IQueryable ReplaceDbContextQueryable(this IQueryable source, DbContext dbContext) + internal static IQueryable ReplaceDbContextQueryable(this IQueryable source, DbContext dbContext,bool isParallelQuery) { - DbContextReplaceQueryableVisitor replaceQueryableVisitor = new DbContextReplaceQueryableVisitor(dbContext); + DbContextReplaceQueryableVisitor replaceQueryableVisitor = new DbContextReplaceQueryableVisitor(dbContext,isParallelQuery); var newExpression = replaceQueryableVisitor.Visit(source.Expression); return replaceQueryableVisitor.Source.Provider.CreateQuery(newExpression); } diff --git a/src/ShardingCore/Sharding/MergeEngines/Abstractions/InMemoryMerge/AbstractInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/Abstractions/InMemoryMerge/AbstractInMemoryAsyncMergeEngine.cs index c7fa1e9f..a48b30c8 100644 --- a/src/ShardingCore/Sharding/MergeEngines/Abstractions/InMemoryMerge/AbstractInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/Abstractions/InMemoryMerge/AbstractInMemoryAsyncMergeEngine.cs @@ -72,7 +72,7 @@ namespace ShardingCore.Sharding.MergeEngines.Abstractions.InMemoryMerge { var shardingDbContext = _mergeContext.CreateDbContext(dsname, tableRouteResult); var newQueryable = (IQueryable)GetStreamMergeContext().GetReWriteQueryable() - .ReplaceDbContextQueryable(shardingDbContext); + .ReplaceDbContextQueryable(shardingDbContext,_mergeContext.IsParallelQuery()); var newCombineQueryable = DoCombineQueryable(newQueryable); return newCombineQueryable ; diff --git a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/AppendOrderSequenceEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/AppendOrderSequenceEnumeratorAsyncStreamMergeEngine.cs index 68432cb1..a5b73180 100644 --- a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/AppendOrderSequenceEnumeratorAsyncStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/AppendOrderSequenceEnumeratorAsyncStreamMergeEngine.cs @@ -116,7 +116,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines. { var shardingDbContext = StreamMergeContext.CreateDbContext(dsname, sequenceResult.TableRouteResult); var newQueryable = (IQueryable)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take).OrderWithExpression(reSetOrders)) - .ReplaceDbContextQueryable(shardingDbContext); + .ReplaceDbContextQueryable(shardingDbContext,StreamMergeContext.IsParallelQuery()); return newQueryable; } diff --git a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs index 5f001d1e..5763a20b 100644 --- a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/DefaultShardingEnumeratorAsyncStreamMergeEngine.cs @@ -48,7 +48,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines.Enumer { var shardingDbContext = StreamMergeContext.CreateDbContext(dsname,tableRouteResult); var newQueryable = (IQueryable)StreamMergeContext.GetReWriteQueryable() - .ReplaceDbContextQueryable(shardingDbContext); + .ReplaceDbContextQueryable(shardingDbContext,StreamMergeContext.IsParallelQuery()); return newQueryable; } diff --git a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs index 45d3d2ee..f0be8223 100644 --- a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/ReverseShardingEnumeratorAsyncStreamMergeEngine.cs @@ -63,7 +63,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines. { var shardingDbContext = StreamMergeContext.CreateDbContext(dsname,tableRouteResult); var newQueryable = (IQueryable)reverseOrderQueryable - .ReplaceDbContextQueryable(shardingDbContext); + .ReplaceDbContextQueryable(shardingDbContext,StreamMergeContext.IsParallelQuery()); return newQueryable; } diff --git a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SequenceEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SequenceEnumeratorAsyncStreamMergeEngine.cs index e3bfab55..cadcdbc1 100644 --- a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SequenceEnumeratorAsyncStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SequenceEnumeratorAsyncStreamMergeEngine.cs @@ -103,7 +103,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines. { var shardingDbContext = StreamMergeContext.CreateDbContext(dsname,sequenceResult.TableRouteResult); var newQueryable = (IQueryable)(noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take)) - .ReplaceDbContextQueryable(shardingDbContext); + .ReplaceDbContextQueryable(shardingDbContext,StreamMergeContext.IsParallelQuery()); return newQueryable; } diff --git a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SingleQueryEnumeratorAsyncStreamMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SingleQueryEnumeratorAsyncStreamMergeEngine.cs index 52bd147c..2ba30eef 100644 --- a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SingleQueryEnumeratorAsyncStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/EnumeratorAsync/SingleQueryEnumeratorAsyncStreamMergeEngine.cs @@ -28,7 +28,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines. var dataSourceName = StreamMergeContext.DataSourceRouteResult.IntersectDataSources.First(); var routeResult = StreamMergeContext.TableRouteResults.First(); var shardingDbContext = StreamMergeContext.CreateDbContext(dataSourceName,routeResult); - var newQueryable = (IQueryable) StreamMergeContext.GetOriginalQueryable().ReplaceDbContextQueryable(shardingDbContext); + var newQueryable = (IQueryable) StreamMergeContext.GetOriginalQueryable().ReplaceDbContextQueryable(shardingDbContext,StreamMergeContext.IsParallelQuery()); if (async) { var asyncEnumerator = GetAsyncEnumerator0(newQueryable).WaitAndUnwrapException(); diff --git a/src/ShardingCore/Sharding/ShardingDbContextExecutors/IDataSourceDbContext.cs b/src/ShardingCore/Sharding/ShardingDbContextExecutors/IDataSourceDbContext.cs index 1adbd075..bf8e1540 100644 --- a/src/ShardingCore/Sharding/ShardingDbContextExecutors/IDataSourceDbContext.cs +++ b/src/ShardingCore/Sharding/ShardingDbContextExecutors/IDataSourceDbContext.cs @@ -18,6 +18,9 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors * @Ver: 1.0 * @Email: 326308290@qq.com */ + /// + /// 同数据源下的dbcontext管理者 + /// public interface IDataSourceDbContext : IDisposable #if !EFCORE2 , IAsyncDisposable diff --git a/src/ShardingCore/Sharding/ShardingDbContextExecutors/NoShardingFirstComparer.cs b/src/ShardingCore/Sharding/ShardingDbContextExecutors/NoShardingFirstComparer.cs index 53a0f467..6df5c43c 100644 --- a/src/ShardingCore/Sharding/ShardingDbContextExecutors/NoShardingFirstComparer.cs +++ b/src/ShardingCore/Sharding/ShardingDbContextExecutors/NoShardingFirstComparer.cs @@ -11,15 +11,28 @@ using ShardingCore.Extensions; */ namespace ShardingCore.Sharding.ShardingDbContextExecutors { + /// + /// 未分表后缀dbcontext排序器 + /// 用来针对data source db context多个迭代的时候优先级,默认未分表的排在第一格 + /// public class NoShardingFirstComparer:IComparer { private readonly string _defaultTail; + /// + /// 未分表后缀dbcontext排序器 + /// public NoShardingFirstComparer() { _defaultTail = new SingleQueryRouteTail(string.Empty).GetRouteTailIdentity(); } + /// + /// 当 x或者y为默认为分表后缀,那么就将对应的排序指定顺序x返回-1,y返回1不进行比较 + /// + /// + /// + /// public int Compare(string? x, string? y) { if (_defaultTail.Equals(x)) diff --git a/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs b/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs index accbc32a..1bdd9d16 100644 --- a/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs +++ b/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs @@ -74,7 +74,7 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors private IDataSourceDbContext GetDataSourceDbContext(string dataSourceName) { - return _dbContextCaches.GetOrAdd(dataSourceName, dsname => new DataSourceDbContext(dataSourceName, _virtualDataSource.IsDefault(dataSourceName), _shardingDbContext, _shardingDbContextOptionsBuilderConfig, _shardingDbContextFactory, _actualConnectionStringManager)); + return _dbContextCaches.GetOrAdd(dataSourceName, dsname => new DataSourceDbContext(dsname, _virtualDataSource.IsDefault(dsname), _shardingDbContext, _shardingDbContextOptionsBuilderConfig, _shardingDbContextFactory, _actualConnectionStringManager)); } /// diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index 5fe49cbd..f26ef5a4 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -215,7 +215,7 @@ namespace ShardingCore.Sharding /// 是否使用并行查询 /// /// - private bool IsParallelQuery() + public bool IsParallelQuery() { return !_shardingConfigOption.AutoTrackEntity|| IsCrossQuery() || IsUseReadWriteSeparation(); } diff --git a/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor.cs b/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor.cs index cc1329b1..4f413744 100644 --- a/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor.cs +++ b/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor.cs @@ -19,11 +19,13 @@ namespace ShardingCore.Core.Internal.Visitors internal class DbContextReplaceQueryableVisitor : ExpressionVisitor { private readonly DbContext _dbContext; + private readonly bool _isParallelQuery; public IQueryable Source; - public DbContextReplaceQueryableVisitor(DbContext dbContext) + public DbContextReplaceQueryableVisitor(DbContext dbContext, bool isParallelQuery) { _dbContext = dbContext; + _isParallelQuery = isParallelQuery; } protected override Expression VisitConstant(ConstantExpression node) @@ -32,11 +34,14 @@ namespace ShardingCore.Core.Internal.Visitors { var dbContextDependencies = typeof(DbContext).GetTypePropertyValue(_dbContext, "DbContextDependencies") as IDbContextDependencies; var targetIQ = (IQueryable)((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource, queryable.ElementType); - //var newQueryable = targetIQ.Provider.CreateQuery((Expression) Expression.Call((Expression) null, typeof(EntityFrameworkQueryableExtensions).GetTypeInfo().GetDeclaredMethod("AsNoTracking").MakeGenericMethod(queryable.ElementType), targetIQ.Expression)); - var newQueryable = targetIQ.Provider.CreateQuery(targetIQ.Expression); + IQueryable newQueryable = null; + if (_isParallelQuery) + newQueryable = targetIQ.Provider.CreateQuery((Expression)Expression.Call((Expression)null, typeof(EntityFrameworkQueryableExtensions).GetTypeInfo().GetDeclaredMethod(nameof(EntityFrameworkQueryableExtensions.AsNoTracking)).MakeGenericMethod(queryable.ElementType), targetIQ.Expression)); + else + newQueryable = targetIQ.Provider.CreateQuery(targetIQ.Expression); Source = newQueryable; // return base.Visit(Expression.Constant(newQueryable)); - return Expression.Constant(newQueryable); + return Expression.Constant(newQueryable); } return base.VisitConstant(node); @@ -45,15 +50,16 @@ namespace ShardingCore.Core.Internal.Visitors #endif #if EFCORE5 || EFCORE6 - internal class DbContextReplaceQueryableVisitor : ExpressionVisitor { private readonly DbContext _dbContext; + private readonly bool _isParallelQuery; public IQueryable Source; - public DbContextReplaceQueryableVisitor(DbContext dbContext) + public DbContextReplaceQueryableVisitor(DbContext dbContext, bool isParallelQuery) { _dbContext = dbContext; + _isParallelQuery = isParallelQuery; } protected override Expression VisitExtension(Expression node) @@ -61,10 +67,13 @@ namespace ShardingCore.Core.Internal.Visitors if (node is QueryRootExpression queryRootExpression) { var dbContextDependencies = typeof(DbContext).GetTypePropertyValue(_dbContext, "DbContextDependencies") as IDbContextDependencies; - var targetIQ = (IQueryable) ((IDbSetCache) _dbContext).GetOrAddSet(dbContextDependencies.SetSource, queryRootExpression.EntityType.ClrType); + var targetIQ = (IQueryable)((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource, queryRootExpression.EntityType.ClrType); //AsNoTracking - //(Expression)Expression.Call((Expression)null, typeof(EntityFrameworkQueryableExtensions).GetTypeInfo().GetDeclaredMethod("AsNoTracking").MakeGenericMethod(queryRootExpression.EntityType.ClrType), targetIQ.Expression) - var newQueryable = targetIQ.Provider.CreateQuery(targetIQ.Expression); + IQueryable newQueryable = null; + if (_isParallelQuery) + newQueryable = targetIQ.Provider.CreateQuery((Expression)Expression.Call((Expression)null, typeof(EntityFrameworkQueryableExtensions).GetTypeInfo().GetDeclaredMethod(nameof(EntityFrameworkQueryableExtensions.AsNoTracking)).MakeGenericMethod(queryRootExpression.EntityType.ClrType), targetIQ.Expression)); + else + newQueryable = targetIQ.Provider.CreateQuery(targetIQ.Expression); Source = newQueryable; //如何替换ef5的set var replaceQueryRoot = new ReplaceSingleQueryRootExpressionVisitor();