From ca0608523e4f8f21f53b1ac710884c40e3a649f9 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Thu, 15 Dec 2022 13:17:53 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=89=93=E7=AE=97?= =?UTF-8?q?=E6=94=AF=E6=8C=81include?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EFCores/EFCore7x/ShardingStateManager.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs new file mode 100644 index 00000000..f0d927d1 --- /dev/null +++ b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Metadata; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.EFCores +{ + public class ShardingStateManager:StateManager + { + private readonly IShardingDbContext _currentShardingDbContext; + + public ShardingStateManager(StateManagerDependencies dependencies) : base(dependencies) + { + + _currentShardingDbContext = (IShardingDbContext)dependencies.CurrentContext; + } + + public override InternalEntityEntry GetOrCreateEntry(object entity) + { + var genericDbContext = _currentShardingDbContext.CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity); + } + + public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) + { + var genericDbContext = _currentShardingDbContext.CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity,entityType); + } + } +} \ No newline at end of file From 3875def0fa7292d5182211794c26ce9276e44f7c Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Thu, 22 Dec 2022 22:47:25 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=AE=80=E6=B4=81?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E7=9A=84=E4=BB=A3=E7=A0=81=E5=B0=86=E9=87=8D?= =?UTF-8?q?=E5=86=99=E5=90=88=E5=B9=B6=E5=88=B0statemanager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DefaultDbContext.cs | 1 - .../DbSetDiscoverExpressionVisitor.cs | 2 +- .../Controllers/WeatherForecastController.cs | 22 +- samples/Sample.MySql/DIExtension.cs | 3 +- .../DbContexts/DefaultShardingDbContext.cs | 8 +- samples/Sample.MySql/Sample.MySql.csproj | 4 +- .../ShardingMySqlMigrationsSqlGenerator.cs | 4 +- .../SysUserModVirtualDataSourceRoute.cs | 4 +- samples/Sample.MySql/Startup.cs | 10 +- .../Core/QueryTrackers/QueryTracker.cs | 2 +- .../EFCores/EFCore2x/ShardingChangeTracker.cs | 4 +- .../EFCores/EFCore2x/ShardingDbSetSource.cs | 62 --- .../EFCore2x/ShardingInternalDbQuery.cs | 27 -- .../EFCores/EFCore2x/ShardingInternalDbSet.cs | 427 ----------------- .../EFCores/EFCore2x/ShardingStateManager.cs | 112 +++++ .../EFCores/EFCore3x/ShardingChangeTracker.cs | 4 +- .../EFCores/EFCore3x/ShardingDbSetSource.cs | 48 -- .../EFCores/EFCore3x/ShardingInternalDbSet.cs | 436 ----------------- .../EFCores/EFCore3x/ShardingStateManager.cs | 111 +++++ .../EFCores/EFCore5x/ShardingChangeTracker.cs | 4 +- .../EFCores/EFCore5x/ShardingDbSetSource.cs | 57 --- .../EFCores/EFCore5x/ShardingInternalDbSet.cs | 439 ------------------ .../EFCores/EFCore5x/ShardingStateManager.cs | 111 +++++ .../EFCores/EFCore6x/ShardingChangeTracker.cs | 4 +- .../EFCores/EFCore6x/ShardingDbSetSource.cs | 57 --- .../EFCores/EFCore6x/ShardingInternalDbSet.cs | 436 ----------------- .../EFCores/EFCore6x/ShardingStateManager.cs | 111 +++++ .../EFCores/EFCore7x/ShardingChangeTracker.cs | 4 +- .../EFCores/EFCore7x/ShardingDbSetSource.cs | 57 --- .../EFCores/EFCore7x/ShardingInternalDbSet.cs | 435 ----------------- .../EFCores/EFCore7x/ShardingStateManager.cs | 86 +++- .../DbContextExtensionShardingCore.cs | 19 +- .../Extensions/ShardingDbContextExtension.cs | 6 +- .../Extensions/ShardingExtension.cs | 2 +- .../Sharding/AbstractShardingDbContext.cs | 365 +-------------- .../Abstractions/IShardingDbContext.cs | 17 - .../IShardingDbContextExecutor.cs | 2 + .../ShardingDbContextExecutor.cs | 7 + .../MergeQueryCompilerContext.cs | 2 +- .../ShardingExecutors/QueryCompilerContext.cs | 2 +- .../Sharding/StreamMergeContext.cs | 2 +- src/ShardingCore/ShardingCoreExtension.cs | 4 +- src6/ShardingCore6/ShardingCore6.csproj | 3 + 43 files changed, 609 insertions(+), 2914 deletions(-) delete mode 100644 src/ShardingCore/EFCores/EFCore2x/ShardingDbSetSource.cs delete mode 100644 src/ShardingCore/EFCores/EFCore2x/ShardingInternalDbQuery.cs delete mode 100644 src/ShardingCore/EFCores/EFCore2x/ShardingInternalDbSet.cs create mode 100644 src/ShardingCore/EFCores/EFCore2x/ShardingStateManager.cs delete mode 100644 src/ShardingCore/EFCores/EFCore3x/ShardingDbSetSource.cs delete mode 100644 src/ShardingCore/EFCores/EFCore3x/ShardingInternalDbSet.cs create mode 100644 src/ShardingCore/EFCores/EFCore3x/ShardingStateManager.cs delete mode 100644 src/ShardingCore/EFCores/EFCore5x/ShardingDbSetSource.cs delete mode 100644 src/ShardingCore/EFCores/EFCore5x/ShardingInternalDbSet.cs create mode 100644 src/ShardingCore/EFCores/EFCore5x/ShardingStateManager.cs delete mode 100644 src/ShardingCore/EFCores/EFCore6x/ShardingDbSetSource.cs delete mode 100644 src/ShardingCore/EFCores/EFCore6x/ShardingInternalDbSet.cs create mode 100644 src/ShardingCore/EFCores/EFCore6x/ShardingStateManager.cs delete mode 100644 src/ShardingCore/EFCores/EFCore7x/ShardingDbSetSource.cs delete mode 100644 src/ShardingCore/EFCores/EFCore7x/ShardingInternalDbSet.cs diff --git a/samples/Sample.AutoCreateIfPresent/DefaultDbContext.cs b/samples/Sample.AutoCreateIfPresent/DefaultDbContext.cs index 85f8fdfd..4fbe53a7 100644 --- a/samples/Sample.AutoCreateIfPresent/DefaultDbContext.cs +++ b/samples/Sample.AutoCreateIfPresent/DefaultDbContext.cs @@ -26,7 +26,6 @@ namespace Sample.AutoCreateIfPresent base.OnModelCreating(modelBuilder); modelBuilder.ApplyConfiguration(new OrderByHourMap()); modelBuilder.ApplyConfiguration(new AreaDeviceMap()); - Console.WriteLine(this.IsExecutor); } public IRouteTail RouteTail { get; set; } diff --git a/samples/Sample.MySql/Controllers/DbSetDiscoverExpressionVisitor.cs b/samples/Sample.MySql/Controllers/DbSetDiscoverExpressionVisitor.cs index fed700fe..699fc65d 100644 --- a/samples/Sample.MySql/Controllers/DbSetDiscoverExpressionVisitor.cs +++ b/samples/Sample.MySql/Controllers/DbSetDiscoverExpressionVisitor.cs @@ -23,7 +23,7 @@ public class DbSetDiscoverExpressionVisitor:ExpressionVisitor where TEn var dbContextDependencies = typeof(DbContext).GetTypePropertyValue(_dbContext, "DbContextDependencies") as IDbContextDependencies; var targetIQ = - ((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource, queryRootExpression.EntityType.ClrType); + ((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource, queryRootExpression.ElementType); DbSet = (DbSet)targetIQ; } return base.VisitExtension(node); diff --git a/samples/Sample.MySql/Controllers/WeatherForecastController.cs b/samples/Sample.MySql/Controllers/WeatherForecastController.cs index b4612a59..35f412bc 100644 --- a/samples/Sample.MySql/Controllers/WeatherForecastController.cs +++ b/samples/Sample.MySql/Controllers/WeatherForecastController.cs @@ -74,17 +74,17 @@ namespace Sample.MySql.Controllers [HttpGet] public async Task Get() { - var virtualDataSource = _shardingRuntimeContext.GetVirtualDataSource(); - virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource("2023", "xxxxxxxx", false)); - var dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager(); - var virtualDataSourceRoute = dataSourceRouteManager.GetRoute(typeof(SysUserMod)); - virtualDataSourceRoute.AddDataSourceName("2023"); - var dataSourceInitializer = _shardingRuntimeContext.GetDataSourceInitializer(); - dataSourceInitializer.InitConfigure("2023",true,true); - using (var dbContextTransaction = _defaultTableDbContext.Database.BeginTransaction()) - { - - } + // var virtualDataSource = _shardingRuntimeContext.GetVirtualDataSource(); + // virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource("2023", "xxxxxxxx", false)); + // var dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager(); + // var virtualDataSourceRoute = dataSourceRouteManager.GetRoute(typeof(SysUserMod)); + // virtualDataSourceRoute.AddDataSourceName("2023"); + // var dataSourceInitializer = _shardingRuntimeContext.GetDataSourceInitializer(); + // dataSourceInitializer.InitConfigure("2023",true,true); + // using (var dbContextTransaction = _defaultTableDbContext.Database.BeginTransaction()) + // { + // + // } var x2 = await (from ut in _defaultTableDbContext.Set() join uu in _defaultTableDbContext.Set() diff --git a/samples/Sample.MySql/DIExtension.cs b/samples/Sample.MySql/DIExtension.cs index 5b65031a..c5c2bc34 100644 --- a/samples/Sample.MySql/DIExtension.cs +++ b/samples/Sample.MySql/DIExtension.cs @@ -38,12 +38,13 @@ namespace Sample.MySql }); } var userModMonths = new List(); + var begin = new DateTime(2021, 1, 01); foreach (var id in ids) { userModMonths.Add(new SysUserLogByMonth() { Id = id.ToString(), - Time = DateTime.Now + Time = begin.AddHours(id*12) }); } diff --git a/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs b/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs index fc5b8d9e..35057f79 100644 --- a/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs +++ b/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs @@ -40,10 +40,10 @@ namespace Sample.MySql.DbContexts modelBuilder.ApplyConfiguration(new SysTestMap()); modelBuilder.ApplyConfiguration(new SysUserLogByMonthMap()); - modelBuilder.Entity().HasData(new SysUserLogByMonth() { Id = "1", Time = DateTime.Now }); - modelBuilder.Entity().HasData(new SysTest() { Id = "1", UserId = "123" }); - modelBuilder.Entity().ToTable(nameof(TestMod)); - modelBuilder.Entity().ToTable(nameof(TestModItem)); + // modelBuilder.Entity().HasData(new SysUserLogByMonth() { Id = "1", Time = DateTime.Now }); + // modelBuilder.Entity().HasData(new SysTest() { Id = "1", UserId = "123" }); + // modelBuilder.Entity().ToTable(nameof(TestMod)); + // modelBuilder.Entity().ToTable(nameof(TestModItem)); } diff --git a/samples/Sample.MySql/Sample.MySql.csproj b/samples/Sample.MySql/Sample.MySql.csproj index fa192a10..886a18bd 100644 --- a/samples/Sample.MySql/Sample.MySql.csproj +++ b/samples/Sample.MySql/Sample.MySql.csproj @@ -12,11 +12,11 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/samples/Sample.MySql/ShardingMySqlMigrationsSqlGenerator.cs b/samples/Sample.MySql/ShardingMySqlMigrationsSqlGenerator.cs index 44fa5380..4105c94d 100644 --- a/samples/Sample.MySql/ShardingMySqlMigrationsSqlGenerator.cs +++ b/samples/Sample.MySql/ShardingMySqlMigrationsSqlGenerator.cs @@ -1,6 +1,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations.Operations; +using Microsoft.EntityFrameworkCore.Update; using Pomelo.EntityFrameworkCore.MySql.Infrastructure.Internal; using Pomelo.EntityFrameworkCore.MySql.Migrations; using ShardingCore.Core.RuntimeContexts; @@ -12,7 +13,8 @@ namespace Sample.MySql { private readonly IShardingRuntimeContext _shardingRuntimeContext; - public ShardingMySqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IRelationalAnnotationProvider annotationProvider, IMySqlOptions options,IShardingRuntimeContext shardingRuntimeContext) : base(dependencies, annotationProvider, options) + + public ShardingMySqlMigrationsSqlGenerator(IShardingRuntimeContext shardingRuntimeContext,MigrationsSqlGeneratorDependencies dependencies, ICommandBatchPreparer commandBatchPreparer, IMySqlOptions options) : base(dependencies, commandBatchPreparer, options) { _shardingRuntimeContext = shardingRuntimeContext; } diff --git a/samples/Sample.MySql/Shardings/SysUserModVirtualDataSourceRoute.cs b/samples/Sample.MySql/Shardings/SysUserModVirtualDataSourceRoute.cs index 51d8c781..be90d450 100644 --- a/samples/Sample.MySql/Shardings/SysUserModVirtualDataSourceRoute.cs +++ b/samples/Sample.MySql/Shardings/SysUserModVirtualDataSourceRoute.cs @@ -9,14 +9,14 @@ public class SysUserModVirtualDataSourceRoute:AbstractShardingOperatorVirtualDat { public override string ShardingKeyToDataSourceName(object shardingKey) { - return $"{((string)shardingKey=="ds1"?"ds1":"ds2")}"; + return $"{shardingKey}"; } public override List GetAllDataSourceNames() { return new List() { - "ds1", "ds2" + "ds0", "ds1", "ds2" }; } diff --git a/samples/Sample.MySql/Startup.cs b/samples/Sample.MySql/Startup.cs index cb1f9c5f..09fea956 100644 --- a/samples/Sample.MySql/Startup.cs +++ b/samples/Sample.MySql/Startup.cs @@ -74,8 +74,8 @@ namespace Sample.MySql .UseRouteConfig(o => { o.AddShardingTableRoute(); - o.AddShardingTableRoute(); - // o.AddShardingTableRoute(); + o.AddShardingTableRoute(); + o.AddShardingTableRoute(); o.AddShardingDataSourceRoute(); o.AddShardingTableRoute(); o.AddShardingTableRoute(); @@ -118,11 +118,11 @@ namespace Sample.MySql //.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); }); o.AddDefaultDataSource("ds0", - "server=127.0.0.1;port=3306;database=dbdbd02;userid=root;password=root;"); + "server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;"); o.AddExtraDataSource(sp => new Dictionary() { - { "ds1", "server=127.0.0.1;port=3306;database=dbdbd12;userid=root;password=root;" }, - { "ds2", "server=127.0.0.1;port=3306;database=dbdbd22;userid=root;password=root;" } + { "ds1", "server=127.0.0.1;port=3306;database=dbdbd1;userid=root;password=root;" }, + { "ds2", "server=127.0.0.1;port=3306;database=dbdbd2;userid=root;password=root;" } }); o.UseShardingMigrationConfigure(b => { diff --git a/src/ShardingCore/Core/QueryTrackers/QueryTracker.cs b/src/ShardingCore/Core/QueryTrackers/QueryTracker.cs index e7042f13..ed550b8a 100644 --- a/src/ShardingCore/Core/QueryTrackers/QueryTracker.cs +++ b/src/ShardingCore/Core/QueryTrackers/QueryTracker.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Core.QueryTrackers { public object Track(object entity, IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(entity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); var attachedEntity = genericDbContext.GetAttachedEntity(entity); if (attachedEntity == null) genericDbContext.Attach(entity); diff --git a/src/ShardingCore/EFCores/EFCore2x/ShardingChangeTracker.cs b/src/ShardingCore/EFCores/EFCore2x/ShardingChangeTracker.cs index 34075184..07f21832 100644 --- a/src/ShardingCore/EFCores/EFCore2x/ShardingChangeTracker.cs +++ b/src/ShardingCore/EFCores/EFCore2x/ShardingChangeTracker.cs @@ -91,7 +91,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } @@ -101,7 +101,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,state,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } diff --git a/src/ShardingCore/EFCores/EFCore2x/ShardingDbSetSource.cs b/src/ShardingCore/EFCores/EFCore2x/ShardingDbSetSource.cs deleted file mode 100644 index b12f8c59..00000000 --- a/src/ShardingCore/EFCores/EFCore2x/ShardingDbSetSource.cs +++ /dev/null @@ -1,62 +0,0 @@ -#if EFCORE2 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; -using System; -using System.Collections.Concurrent; -using System.Reflection; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: Saturday, 14 August 2021 10:17:43 - * @Email: 326308290@qq.com - */ - - /// - /// This API supports the Entity Framework Core infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public class ShardingDbSetSource : IDbSetSource, IDbQuerySource - { - private static readonly MethodInfo _genericCreateSet - = typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateSetFactory)); - - private static readonly MethodInfo _genericCreateQuery - = typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateQueryFactory)); - - private readonly ConcurrentDictionary> _cache - = new ConcurrentDictionary>(); - - /// - /// This API supports the Entity Framework Core infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public virtual object Create(DbContext context, Type type) - => CreateCore(context, type, _genericCreateSet); - - /// - /// This API supports the Entity Framework Core infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public virtual object CreateQuery(DbContext context, Type type) - => CreateCore(context, type, _genericCreateQuery); - - private object CreateCore(DbContext context, Type type, MethodInfo createMethod) - => _cache.GetOrAdd( - type, - t => (Func)createMethod - .MakeGenericMethod(t) - .Invoke(null, null))(context); - - private static Func CreateSetFactory() - where TEntity : class - => c => new ShardingInternalDbSet(c); - - private static Func> CreateQueryFactory() - where TQuery : class - => c => new ShardingInternalDbQuery(c); - } -} -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore2x/ShardingInternalDbQuery.cs b/src/ShardingCore/EFCores/EFCore2x/ShardingInternalDbQuery.cs deleted file mode 100644 index 37aca469..00000000 --- a/src/ShardingCore/EFCores/EFCore2x/ShardingInternalDbQuery.cs +++ /dev/null @@ -1,27 +0,0 @@ -#if EFCORE2 -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/8/20 17:05:36 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - - - public class ShardingInternalDbQuery : InternalDbQuery where TQuery : class - { - public ShardingInternalDbQuery(DbContext context) : base(context) - { - } - } - -} -#endif diff --git a/src/ShardingCore/EFCores/EFCore2x/ShardingInternalDbSet.cs b/src/ShardingCore/EFCores/EFCore2x/ShardingInternalDbSet.cs deleted file mode 100644 index 039fe3ba..00000000 --- a/src/ShardingCore/EFCores/EFCore2x/ShardingInternalDbSet.cs +++ /dev/null @@ -1,427 +0,0 @@ -#if EFCORE2 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Internal; -using ShardingCore.Core; -using ShardingCore.Sharding.Abstractions; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Infrastructure; -using ShardingCore.Core.EntityMetadatas; -using ShardingCore.Core.RuntimeContexts; -using ShardingCore.Core.TrackerManagers; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources; -using ShardingCore.Core.VirtualRoutes.Abstractions; -using ShardingCore.Exceptions; -using ShardingCore.Extensions; -using ShardingCore.Utils; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/8/15 8:39:15 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - - public class ShardingInternalDbSet : InternalDbSet - where TEntity : class - { - private readonly IShardingDbContext _context; - private readonly IShardingRuntimeContext _shardingRuntimeContext; - private LocalView? _localView; - - public ShardingInternalDbSet(DbContext context) : base(context) - { - _context = (IShardingDbContext)context; - _shardingRuntimeContext = context.GetShardingRuntimeContext(); - } - - private IDataSourceRouteManager _dataSourceRouteManager; - - protected IDataSourceRouteManager DataSourceRouteManager - { - get - { - if (null == _dataSourceRouteManager) - { - _dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager(); - } - - return _dataSourceRouteManager; - } - } - - public override LocalView Local - { - get - { - - if (((DbContext)_context).ChangeTracker.AutoDetectChangesEnabled) - { - ((DbContext)_context).ChangeTracker.DetectChanges(); - } - - return _localView ??= new ShardingLocalView(this); - } - } - private ITableRouteManager _tableRouteManager; - - protected ITableRouteManager TableRouteManager - { - get - { - if (null == _tableRouteManager) - { - _tableRouteManager = _shardingRuntimeContext.GetTableRouteManager(); - } - - return _tableRouteManager; - } - } - - private IEntityMetadataManager _entityMetadataManager; - - protected IEntityMetadataManager EntityMetadataManager - { - get - { - if (null == _entityMetadataManager) - { - _entityMetadataManager = _shardingRuntimeContext.GetEntityMetadataManager(); - } - - return _entityMetadataManager; - } - } - - private ITrackerManager _trackerManager; - - protected ITrackerManager TrackerManager - { - get - { - if (null == _trackerManager) - { - _trackerManager = _shardingRuntimeContext.GetTrackerManager(); - } - - return _trackerManager; - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Add(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Add(entity); - } - - public override async Task> AddAsync(TEntity entity, CancellationToken cancellationToken = - new CancellationToken()) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return await genericDbContext.Set().AddAsync(entity, cancellationToken); - } - - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Attach(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Attach(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Remove(TEntity entity) - { - Check.NotNull(entity, nameof(entity)); - - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Remove(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Update(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Update(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(params TEntity[] entities) - { - Check.NotNull(entities, nameof(entities)); - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync( - IEnumerable entities, - CancellationToken cancellationToken = default) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value, cancellationToken); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(IEnumerable entities) - { - Check.NotNull(entities, nameof(entities)); - - - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - private Dictionary> AggregateToDic(IEnumerable entities) - { - return entities.Select(o => - { - var dbContext = _context.CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext).ToDictionary(o => o.Key, o => o.Select(g => g.Entity)); - } - - public override TEntity Find(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().Find(keyValues); - } - - return base.Find(keyValues); - } - - public override Task FindAsync(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues); - } - return base.FindAsync(keyValues); - } - - public override Task FindAsync(object[] keyValues, CancellationToken cancellationToken) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues, cancellationToken); - } - return base.FindAsync(keyValues, cancellationToken); - } - - private DbContext GetDbContextByKeyValue(params object[] keyValues) - { - var entityMetadata = EntityMetadataManager.TryGet(typeof(TEntity)); - if (entityMetadata == null) - { - throw new ShardingCoreInvalidOperationException( - $"cant found type:[{typeof(TEntity)}] in {nameof(IEntityMetadataManager)}"); - } - - //既不是分表也不是分库的话就是默认对象 - if (!entityMetadata.IsShardingTable() && !entityMetadata.IsShardingDataSource()) - { - var defaultDataSourceName = _shardingRuntimeContext.GetVirtualDataSource().DefaultDataSourceName; - var routeTailFactory = _shardingRuntimeContext.GetRouteTailFactory(); - var routeTail = routeTailFactory.Create(string.Empty); - return _context.GetShareDbContext(defaultDataSourceName, routeTail); - } - - if (keyValues.Length == 1) - { - //单key字段 - if (entityMetadata.IsSingleKey) - { - var isShardingDataSource = entityMetadata.IsShardingDataSource(); - var shardingDataSourceFieldIsKey = entityMetadata.ShardingDataSourceFieldIsKey(); - if (isShardingDataSource && !shardingDataSourceFieldIsKey) - return null; - var isShardingTable = entityMetadata.IsShardingTable(); - var shardingTableFieldIsKey = entityMetadata.ShardingTableFieldIsKey(); - if (isShardingTable && !shardingTableFieldIsKey) - return null; - var primaryKeyValue = keyValues[0]; - if (primaryKeyValue != null) - { - var dataSourceName = GetDataSourceName(primaryKeyValue); - var realEntityType = TrackerManager.TranslateEntityType(typeof(TEntity)); - var tableTail = TableRouteManager.GetTableTail(dataSourceName, primaryKeyValue,realEntityType); - var routeTail = _shardingRuntimeContext.GetRouteTailFactory().Create(tableTail); - return _context.GetShareDbContext(dataSourceName, routeTail); - } - } - } - - return null; - } - - private string GetDataSourceName(object shardingKeyValue) - { - return DataSourceRouteManager.GetDataSourceName(shardingKeyValue); - } - } -} -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore2x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore2x/ShardingStateManager.cs new file mode 100644 index 00000000..41dee844 --- /dev/null +++ b/src/ShardingCore/EFCores/EFCore2x/ShardingStateManager.cs @@ -0,0 +1,112 @@ +#if EFCORE2 + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.EFCores +{ + public class ShardingStateManager:StateManager + { + private readonly DbContext _currentDbContext; + private readonly IShardingDbContext _currentShardingDbContext; + + public ShardingStateManager(StateManagerDependencies dependencies) : base(dependencies) + { + _currentDbContext=dependencies.CurrentContext.Context; + _currentShardingDbContext = (IShardingDbContext)_currentDbContext; + } + + public override InternalEntityEntry GetOrCreateEntry(object entity) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity); + } + + public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity,entityType); + } + + public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer, + ISet handledForeignKeys) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer, handledForeignKeys); + } + + public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + } + + public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, entityType); + } + + public override int SaveChanges(bool acceptAllChangesOnSuccess) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled&&_currentDbContext.Database.CurrentTransaction==null&&_currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = _currentDbContext.Database.BeginTransaction()) + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + tran.Commit(); + } + } + else + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + } + + return i; + } + + public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled && _currentDbContext.Database.CurrentTransaction==null && _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = await _currentDbContext.Database.BeginTransactionAsync(cancellationToken)) + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + tran.Commit(); + } + } + else + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + } + + + return i; + } + } +} +#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore3x/ShardingChangeTracker.cs b/src/ShardingCore/EFCores/EFCore3x/ShardingChangeTracker.cs index 402a5e84..d21237c3 100644 --- a/src/ShardingCore/EFCores/EFCore3x/ShardingChangeTracker.cs +++ b/src/ShardingCore/EFCores/EFCore3x/ShardingChangeTracker.cs @@ -92,7 +92,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } @@ -102,7 +102,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,state,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } diff --git a/src/ShardingCore/EFCores/EFCore3x/ShardingDbSetSource.cs b/src/ShardingCore/EFCores/EFCore3x/ShardingDbSetSource.cs deleted file mode 100644 index 1dcfbe53..00000000 --- a/src/ShardingCore/EFCores/EFCore3x/ShardingDbSetSource.cs +++ /dev/null @@ -1,48 +0,0 @@ -#if EFCORE3 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; -using System; -using System.Collections.Concurrent; -using System.Reflection; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: Saturday, 14 August 2021 10:17:43 - * @Email: 326308290@qq.com - */ - - public class ShardingDbSetSource:IDbSetSource - { - - private static readonly MethodInfo _genericCreateSet - = typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateSetFactory)); - - private readonly ConcurrentDictionary> _cache - = new ConcurrentDictionary>(); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual object Create(DbContext context, Type type) - => CreateCore(context, type, _genericCreateSet); - - private object CreateCore(DbContext context, Type type, MethodInfo createMethod) - => _cache.GetOrAdd( - type, - t => (Func)createMethod - .MakeGenericMethod(t) - .Invoke(null, null))(context); - - private static Func CreateSetFactory() - where TEntity : class - => c => new ShardingInternalDbSet(c); - } - -} -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore3x/ShardingInternalDbSet.cs b/src/ShardingCore/EFCores/EFCore3x/ShardingInternalDbSet.cs deleted file mode 100644 index 6b04618d..00000000 --- a/src/ShardingCore/EFCores/EFCore3x/ShardingInternalDbSet.cs +++ /dev/null @@ -1,436 +0,0 @@ -#if EFCORE3 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Internal; -using ShardingCore.Core; -using ShardingCore.Sharding.Abstractions; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Infrastructure; -using ShardingCore.Core.EntityMetadatas; -using ShardingCore.Core.RuntimeContexts; -using ShardingCore.Core.TrackerManagers; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources; -using ShardingCore.Core.VirtualRoutes.Abstractions; -using ShardingCore.Exceptions; -using ShardingCore.Extensions; -using ShardingCore.Utils; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/8/15 8:39:15 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - - public class ShardingInternalDbSet : InternalDbSet - where TEntity : class - { - private readonly IShardingDbContext _context; - private readonly IShardingRuntimeContext _shardingRuntimeContext; - private LocalView? _localView; - - - public ShardingInternalDbSet(DbContext context) : base(context) - { - _context = (IShardingDbContext)context; - _shardingRuntimeContext = context.GetShardingRuntimeContext(); - } - - private IDataSourceRouteManager _dataSourceRouteManager; - - protected IDataSourceRouteManager DataSourceRouteManager - { - get - { - if (null == _dataSourceRouteManager) - { - _dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager(); - } - - return _dataSourceRouteManager; - } - } - - public override LocalView Local - { - get - { - - if (((DbContext)_context).ChangeTracker.AutoDetectChangesEnabled) - { - ((DbContext)_context).ChangeTracker.DetectChanges(); - } - - return _localView ??= new ShardingLocalView(this); - } - } - private ITableRouteManager _tableRouteManager; - - protected ITableRouteManager TableRouteManager - { - get - { - if (null == _tableRouteManager) - { - _tableRouteManager = _shardingRuntimeContext.GetTableRouteManager(); - } - - return _tableRouteManager; - } - } - - private IEntityMetadataManager _entityMetadataManager; - - protected IEntityMetadataManager EntityMetadataManager - { - get - { - if (null == _entityMetadataManager) - { - _entityMetadataManager = _shardingRuntimeContext.GetEntityMetadataManager(); - } - - return _entityMetadataManager; - } - } - - private ITrackerManager _trackerManager; - - protected ITrackerManager TrackerManager - { - get - { - if (null == _trackerManager) - { - _trackerManager = _shardingRuntimeContext.GetTrackerManager(); - } - - return _trackerManager; - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Add(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Add(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async ValueTask> AddAsync( - TEntity entity, - CancellationToken cancellationToken = default) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return await genericDbContext.Set().AddAsync(entity, cancellationToken); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Attach(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Attach(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Remove(TEntity entity) - { - Check.NotNull(entity, nameof(entity)); - - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Remove(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Update(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Update(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(params TEntity[] entities) - { - Check.NotNull(entities, nameof(entities)); - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync( - IEnumerable entities, - CancellationToken cancellationToken = default) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value, cancellationToken); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(IEnumerable entities) - { - Check.NotNull(entities, nameof(entities)); - - - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - private Dictionary> AggregateToDic(IEnumerable entities) - { - return entities.Select(o => - { - var dbContext = _context.CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext).ToDictionary(o => o.Key, o => o.Select(g => g.Entity)); - } - - public override TEntity Find(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().Find(keyValues); - } - - return base.Find(keyValues); - } - - public override ValueTask FindAsync(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues); - } - - return base.FindAsync(keyValues); - } - - public override ValueTask FindAsync(object[] keyValues, CancellationToken cancellationToken) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues, cancellationToken); - } - - return base.FindAsync(keyValues, cancellationToken); - } - - private DbContext GetDbContextByKeyValue(params object[] keyValues) - { - var entityMetadata = EntityMetadataManager.TryGet(typeof(TEntity)); - if (entityMetadata == null) - { - throw new ShardingCoreInvalidOperationException( - $"cant found type:[{typeof(TEntity)}] in {nameof(IEntityMetadataManager)}"); - } - - //既不是分表也不是分库的话就是默认对象 - if (!entityMetadata.IsShardingTable() && !entityMetadata.IsShardingDataSource()) - { - var defaultDataSourceName = _shardingRuntimeContext.GetVirtualDataSource().DefaultDataSourceName; - var routeTailFactory = _shardingRuntimeContext.GetRouteTailFactory(); - var routeTail = routeTailFactory.Create(string.Empty); - return _context.GetShareDbContext(defaultDataSourceName, routeTail); - } - - if (keyValues.Length == 1) - { - //单key字段 - if (entityMetadata.IsSingleKey) - { - var isShardingDataSource = entityMetadata.IsShardingDataSource(); - var shardingDataSourceFieldIsKey = entityMetadata.ShardingDataSourceFieldIsKey(); - if (isShardingDataSource && !shardingDataSourceFieldIsKey) - return null; - var isShardingTable = entityMetadata.IsShardingTable(); - var shardingTableFieldIsKey = entityMetadata.ShardingTableFieldIsKey(); - if (isShardingTable && !shardingTableFieldIsKey) - return null; - var primaryKeyValue = keyValues[0]; - if (primaryKeyValue != null) - { - var dataSourceName = GetDataSourceName(primaryKeyValue); - var realEntityType = TrackerManager.TranslateEntityType(typeof(TEntity)); - var tableTail = TableRouteManager.GetTableTail(dataSourceName, primaryKeyValue,realEntityType); - var routeTail = _shardingRuntimeContext.GetRouteTailFactory().Create(tableTail); - return _context.GetShareDbContext(dataSourceName, routeTail); - } - } - } - - return null; - } - - private string GetDataSourceName(object shardingKeyValue) - { - return DataSourceRouteManager.GetDataSourceName(shardingKeyValue); - } - } -} -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore3x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore3x/ShardingStateManager.cs new file mode 100644 index 00000000..7b745e21 --- /dev/null +++ b/src/ShardingCore/EFCores/EFCore3x/ShardingStateManager.cs @@ -0,0 +1,111 @@ +#if EFCORE3 + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.EFCores +{ + public class ShardingStateManager:StateManager + { + private readonly DbContext _currentDbContext; + private readonly IShardingDbContext _currentShardingDbContext; + + public ShardingStateManager(StateManagerDependencies dependencies) : base(dependencies) + { + _currentDbContext=dependencies.CurrentContext.Context; + _currentShardingDbContext = (IShardingDbContext)_currentDbContext; + } + + public override InternalEntityEntry GetOrCreateEntry(object entity) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity); + } + + public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity,entityType); + } + + public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer); + } + + public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + } + + public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, entityType, throwOnTypeMismatch); + } + + public override int SaveChanges(bool acceptAllChangesOnSuccess) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled&&_currentDbContext.Database.CurrentTransaction==null&&_currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = _currentDbContext.Database.BeginTransaction()) + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + tran.Commit(); + } + } + else + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + } + + return i; + } + + public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled && _currentDbContext.Database.CurrentTransaction==null && _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = await _currentDbContext.Database.BeginTransactionAsync(cancellationToken)) + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + await tran.CommitAsync(cancellationToken); + } + } + else + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + } + + + return i; + } + } +} +#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore5x/ShardingChangeTracker.cs b/src/ShardingCore/EFCores/EFCore5x/ShardingChangeTracker.cs index fce94d2a..d03e8907 100644 --- a/src/ShardingCore/EFCores/EFCore5x/ShardingChangeTracker.cs +++ b/src/ShardingCore/EFCores/EFCore5x/ShardingChangeTracker.cs @@ -91,7 +91,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } @@ -101,7 +101,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,state,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } diff --git a/src/ShardingCore/EFCores/EFCore5x/ShardingDbSetSource.cs b/src/ShardingCore/EFCores/EFCore5x/ShardingDbSetSource.cs deleted file mode 100644 index 765dfa80..00000000 --- a/src/ShardingCore/EFCores/EFCore5x/ShardingDbSetSource.cs +++ /dev/null @@ -1,57 +0,0 @@ -#if EFCORE5 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; -using System; -using System.Collections.Concurrent; -using System.Reflection; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: Saturday, 14 August 2021 10:17:43 - * @Email: 326308290@qq.com - */ - - public class ShardingDbSetSource : IDbSetSource - { - - private static readonly MethodInfo _genericCreateSet - = typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateSetFactory)); - - private readonly ConcurrentDictionary<(Type Type, string Name), Func> _cache - = new ConcurrentDictionary<(Type Type, string Name), Func>(); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual object Create(DbContext context, Type type) - => CreateCore(context, type, null, _genericCreateSet); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual object Create(DbContext context, string name, Type type) - => CreateCore(context, type, name, _genericCreateSet); - - private object CreateCore(DbContext context, Type type, string name, MethodInfo createMethod) - => _cache.GetOrAdd( - (type, name), - t => (Func)createMethod - .MakeGenericMethod(t.Type) - .Invoke(null, null))(context, name); - - private static Func CreateSetFactory() - where TEntity : class - => (c, name) => new ShardingInternalDbSet(c, name); - } - -} -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore5x/ShardingInternalDbSet.cs b/src/ShardingCore/EFCores/EFCore5x/ShardingInternalDbSet.cs deleted file mode 100644 index 6f11210b..00000000 --- a/src/ShardingCore/EFCores/EFCore5x/ShardingInternalDbSet.cs +++ /dev/null @@ -1,439 +0,0 @@ -#if EFCORE5 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Internal; -using ShardingCore.Core; -using ShardingCore.Sharding.Abstractions; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Infrastructure; -using ShardingCore.Core.EntityMetadatas; -using ShardingCore.Core.RuntimeContexts; -using ShardingCore.Core.TrackerManagers; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources; -using ShardingCore.Core.VirtualRoutes.Abstractions; -using ShardingCore.Exceptions; -using ShardingCore.Extensions; -using ShardingCore.Utils; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/8/15 8:39:15 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - - public class ShardingInternalDbSet : InternalDbSet - where TEntity : class - { - private readonly IShardingDbContext _context; - private readonly IShardingRuntimeContext _shardingRuntimeContext; - private LocalView? _localView; - - - - public ShardingInternalDbSet(DbContext context, string entityTypeName) : base(context, entityTypeName) - { - _context = (IShardingDbContext)context; - _shardingRuntimeContext = context.GetShardingRuntimeContext(); - } - - private IDataSourceRouteManager _dataSourceRouteManager; - - protected IDataSourceRouteManager DataSourceRouteManager - { - get - { - if (null == _dataSourceRouteManager) - { - _dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager(); - } - - return _dataSourceRouteManager; - } - } - - public override LocalView Local - { - get - { - - if (((DbContext)_context).ChangeTracker.AutoDetectChangesEnabled) - { - ((DbContext)_context).ChangeTracker.DetectChanges(); - } - - return _localView ??= new ShardingLocalView(this); - } - } - private ITableRouteManager _tableRouteManager; - - protected ITableRouteManager TableRouteManager - { - get - { - if (null == _tableRouteManager) - { - _tableRouteManager = _shardingRuntimeContext.GetTableRouteManager(); - } - - return _tableRouteManager; - } - } - - private IEntityMetadataManager _entityMetadataManager; - - protected IEntityMetadataManager EntityMetadataManager - { - get - { - if (null == _entityMetadataManager) - { - _entityMetadataManager = _shardingRuntimeContext.GetEntityMetadataManager(); - } - - return _entityMetadataManager; - } - } - - private ITrackerManager _trackerManager; - - protected ITrackerManager TrackerManager - { - get - { - if (null == _trackerManager) - { - _trackerManager = _shardingRuntimeContext.GetTrackerManager(); - } - - return _trackerManager; - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Add(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Add(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async ValueTask> AddAsync( - TEntity entity, - CancellationToken cancellationToken = default) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return await genericDbContext.Set().AddAsync(entity, cancellationToken); - } - - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Attach(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Attach(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Remove(TEntity entity) - { - Check.NotNull(entity, nameof(entity)); - - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Remove(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Update(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Update(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(params TEntity[] entities) - { - Check.NotNull(entities, nameof(entities)); - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync( - IEnumerable entities, - CancellationToken cancellationToken = default) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value, cancellationToken); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(IEnumerable entities) - { - Check.NotNull(entities, nameof(entities)); - - - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - private Dictionary> AggregateToDic(IEnumerable entities) - { - return entities.Select(o => - { - var dbContext = _context.CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext).ToDictionary(o => o.Key, o => o.Select(g => g.Entity)); - } - - public override TEntity Find(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().Find(keyValues); - } - - return base.Find(keyValues); - } - - public override ValueTask FindAsync(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues); - } - - return base.FindAsync(keyValues); - } - - public override ValueTask FindAsync(object[] keyValues, CancellationToken cancellationToken) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues, cancellationToken); - } - - return base.FindAsync(keyValues, cancellationToken); - } - - - private DbContext GetDbContextByKeyValue(params object[] keyValues) - { - var entityMetadata = EntityMetadataManager.TryGet(typeof(TEntity)); - if (entityMetadata == null) - { - throw new ShardingCoreInvalidOperationException( - $"cant found type:[{typeof(TEntity)}] in {nameof(IEntityMetadataManager)}"); - } - - //既不是分表也不是分库的话就是默认对象 - if (!entityMetadata.IsShardingTable() && !entityMetadata.IsShardingDataSource()) - { - var defaultDataSourceName = _shardingRuntimeContext.GetVirtualDataSource().DefaultDataSourceName; - var routeTailFactory = _shardingRuntimeContext.GetRouteTailFactory(); - var routeTail = routeTailFactory.Create(string.Empty); - return _context.GetShareDbContext(defaultDataSourceName, routeTail); - } - - if (keyValues.Length == 1) - { - //单key字段 - if (entityMetadata.IsSingleKey) - { - var isShardingDataSource = entityMetadata.IsShardingDataSource(); - var shardingDataSourceFieldIsKey = entityMetadata.ShardingDataSourceFieldIsKey(); - if (isShardingDataSource && !shardingDataSourceFieldIsKey) - return null; - var isShardingTable = entityMetadata.IsShardingTable(); - var shardingTableFieldIsKey = entityMetadata.ShardingTableFieldIsKey(); - if (isShardingTable && !shardingTableFieldIsKey) - return null; - var primaryKeyValue = keyValues[0]; - if (primaryKeyValue != null) - { - var dataSourceName = GetDataSourceName(primaryKeyValue); - var realEntityType = TrackerManager.TranslateEntityType(typeof(TEntity)); - var tableTail = TableRouteManager.GetTableTail(dataSourceName, primaryKeyValue,realEntityType); - var routeTail = _shardingRuntimeContext.GetRouteTailFactory().Create(tableTail); - return _context.GetShareDbContext(dataSourceName, routeTail); - } - } - } - - return null; - } - - private string GetDataSourceName(object shardingKeyValue) - { - return DataSourceRouteManager.GetDataSourceName(shardingKeyValue); - } - } -} -#endif diff --git a/src/ShardingCore/EFCores/EFCore5x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore5x/ShardingStateManager.cs new file mode 100644 index 00000000..c2d13098 --- /dev/null +++ b/src/ShardingCore/EFCores/EFCore5x/ShardingStateManager.cs @@ -0,0 +1,111 @@ +#if EFCORE5 + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.EFCores +{ + public class ShardingStateManager:StateManager + { + private readonly DbContext _currentDbContext; + private readonly IShardingDbContext _currentShardingDbContext; + + public ShardingStateManager(StateManagerDependencies dependencies) : base(dependencies) + { + _currentDbContext=dependencies.CurrentContext.Context; + _currentShardingDbContext = (IShardingDbContext)_currentDbContext; + } + + public override InternalEntityEntry GetOrCreateEntry(object entity) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity); + } + + public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity,entityType); + } + + public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer); + } + + public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + } + + public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, entityType, throwOnTypeMismatch); + } + + public override int SaveChanges(bool acceptAllChangesOnSuccess) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled&&_currentDbContext.Database.CurrentTransaction==null&&_currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = _currentDbContext.Database.BeginTransaction()) + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + tran.Commit(); + } + } + else + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + } + + return i; + } + + public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled && _currentDbContext.Database.CurrentTransaction==null && _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = await _currentDbContext.Database.BeginTransactionAsync(cancellationToken)) + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + await tran.CommitAsync(cancellationToken); + } + } + else + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + } + + + return i; + } + } +} +#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore6x/ShardingChangeTracker.cs b/src/ShardingCore/EFCores/EFCore6x/ShardingChangeTracker.cs index 7587b870..46685657 100644 --- a/src/ShardingCore/EFCores/EFCore6x/ShardingChangeTracker.cs +++ b/src/ShardingCore/EFCores/EFCore6x/ShardingChangeTracker.cs @@ -91,7 +91,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } @@ -101,7 +101,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,state,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } diff --git a/src/ShardingCore/EFCores/EFCore6x/ShardingDbSetSource.cs b/src/ShardingCore/EFCores/EFCore6x/ShardingDbSetSource.cs deleted file mode 100644 index 2cea7146..00000000 --- a/src/ShardingCore/EFCores/EFCore6x/ShardingDbSetSource.cs +++ /dev/null @@ -1,57 +0,0 @@ -#if EFCORE6 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; -using System; -using System.Collections.Concurrent; -using System.Reflection; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: Saturday, 14 August 2021 10:17:43 - * @Email: 326308290@qq.com - */ - - public class ShardingDbSetSource : IDbSetSource - { - - private static readonly MethodInfo _genericCreateSet - = typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateSetFactory)); - - private readonly ConcurrentDictionary<(Type Type, string Name), Func> _cache - = new ConcurrentDictionary<(Type Type, string Name), Func>(); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual object Create(DbContext context, Type type) - => CreateCore(context, type, null, _genericCreateSet); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual object Create(DbContext context, string name, Type type) - => CreateCore(context, type, name, _genericCreateSet); - - private object CreateCore(DbContext context, Type type, string name, MethodInfo createMethod) - => _cache.GetOrAdd( - (type, name), - t => (Func)createMethod - .MakeGenericMethod(t.Type) - .Invoke(null, null))(context, name); - - private static Func CreateSetFactory() - where TEntity : class - => (c, name) => new ShardingInternalDbSet(c, name); - } - -} -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore6x/ShardingInternalDbSet.cs b/src/ShardingCore/EFCores/EFCore6x/ShardingInternalDbSet.cs deleted file mode 100644 index e95d1891..00000000 --- a/src/ShardingCore/EFCores/EFCore6x/ShardingInternalDbSet.cs +++ /dev/null @@ -1,436 +0,0 @@ -#if EFCORE6 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Internal; -using ShardingCore.Core; -using ShardingCore.Sharding.Abstractions; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Infrastructure; -using ShardingCore.Core.EntityMetadatas; -using ShardingCore.Core.RuntimeContexts; -using ShardingCore.Core.TrackerManagers; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources; -using ShardingCore.Core.VirtualRoutes.Abstractions; -using ShardingCore.Exceptions; -using ShardingCore.Extensions; -using ShardingCore.Utils; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/8/15 8:39:15 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public class ShardingInternalDbSet : InternalDbSet - where TEntity : class - { - private readonly IShardingDbContext _context; - private readonly IShardingRuntimeContext _shardingRuntimeContext; - private LocalView? _localView; - - - - public ShardingInternalDbSet(DbContext context, string entityTypeName) : base(context, entityTypeName) - { - _context = (IShardingDbContext)context; - _shardingRuntimeContext = context.GetShardingRuntimeContext(); - } - - private IDataSourceRouteManager _dataSourceRouteManager; - - protected IDataSourceRouteManager DataSourceRouteManager - { - get - { - if (null == _dataSourceRouteManager) - { - _dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager(); - } - - return _dataSourceRouteManager; - } - } - - public override LocalView Local - { - get - { - - if (((DbContext)_context).ChangeTracker.AutoDetectChangesEnabled) - { - ((DbContext)_context).ChangeTracker.DetectChanges(); - } - - return _localView ??= new ShardingLocalView(this); - } - } - private ITableRouteManager _tableRouteManager; - - protected ITableRouteManager TableRouteManager - { - get - { - if (null == _tableRouteManager) - { - _tableRouteManager = _shardingRuntimeContext.GetTableRouteManager(); - } - - return _tableRouteManager; - } - } - - private IEntityMetadataManager _entityMetadataManager; - - protected IEntityMetadataManager EntityMetadataManager - { - get - { - if (null == _entityMetadataManager) - { - _entityMetadataManager = _shardingRuntimeContext.GetEntityMetadataManager(); - } - - return _entityMetadataManager; - } - } - - private ITrackerManager _trackerManager; - - protected ITrackerManager TrackerManager - { - get - { - if (null == _trackerManager) - { - _trackerManager = _shardingRuntimeContext.GetTrackerManager(); - } - - return _trackerManager; - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Add(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Add(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async ValueTask> AddAsync( - TEntity entity, - CancellationToken cancellationToken = default) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return await genericDbContext.Set().AddAsync(entity, cancellationToken); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Attach(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Attach(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Remove(TEntity entity) - { - Check.NotNull(entity, nameof(entity)); - - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Remove(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Update(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Update(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(params TEntity[] entities) - { - Check.NotNull(entities, nameof(entities)); - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync( - IEnumerable entities, - CancellationToken cancellationToken = default) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value, cancellationToken); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(IEnumerable entities) - { - Check.NotNull(entities, nameof(entities)); - - - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - private Dictionary> AggregateToDic(IEnumerable entities) - { - return entities.Select(o => - { - var dbContext = _context.CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext).ToDictionary(o => o.Key, o => o.Select(g => g.Entity)); - } - - public override TEntity Find(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().Find(keyValues); - } - - return base.Find(keyValues); - } - - public override ValueTask FindAsync(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues); - } - - return base.FindAsync(keyValues); - } - - public override ValueTask FindAsync(object[] keyValues, CancellationToken cancellationToken) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues, cancellationToken); - } - - return base.FindAsync(keyValues, cancellationToken); - } - - private DbContext GetDbContextByKeyValue(params object[] keyValues) - { - var entityMetadata = EntityMetadataManager.TryGet(typeof(TEntity)); - if (entityMetadata == null) - { - throw new ShardingCoreInvalidOperationException( - $"cant found type:[{typeof(TEntity)}] in {nameof(IEntityMetadataManager)}"); - } - - //既不是分表也不是分库的话就是默认对象 - if (!entityMetadata.IsShardingTable() && !entityMetadata.IsShardingDataSource()) - { - var defaultDataSourceName = _shardingRuntimeContext.GetVirtualDataSource().DefaultDataSourceName; - var routeTailFactory = _shardingRuntimeContext.GetRouteTailFactory(); - var routeTail = routeTailFactory.Create(string.Empty); - return _context.GetShareDbContext(defaultDataSourceName, routeTail); - } - - if (keyValues.Length == 1) - { - //单key字段 - if (entityMetadata.IsSingleKey) - { - var isShardingDataSource = entityMetadata.IsShardingDataSource(); - var shardingDataSourceFieldIsKey = entityMetadata.ShardingDataSourceFieldIsKey(); - if (isShardingDataSource && !shardingDataSourceFieldIsKey) - return null; - var isShardingTable = entityMetadata.IsShardingTable(); - var shardingTableFieldIsKey = entityMetadata.ShardingTableFieldIsKey(); - if (isShardingTable && !shardingTableFieldIsKey) - return null; - var primaryKeyValue = keyValues[0]; - if (primaryKeyValue != null) - { - var dataSourceName = GetDataSourceName(primaryKeyValue); - var realEntityType = TrackerManager.TranslateEntityType(typeof(TEntity)); - var tableTail = TableRouteManager.GetTableTail(dataSourceName, primaryKeyValue,realEntityType); - var routeTail = _shardingRuntimeContext.GetRouteTailFactory().Create(tableTail); - return _context.GetShareDbContext(dataSourceName, routeTail); - } - } - } - - return null; - } - - private string GetDataSourceName(object shardingKeyValue) - { - return DataSourceRouteManager.GetDataSourceName(shardingKeyValue); - } - } -} -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore6x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore6x/ShardingStateManager.cs new file mode 100644 index 00000000..3f3149e3 --- /dev/null +++ b/src/ShardingCore/EFCores/EFCore6x/ShardingStateManager.cs @@ -0,0 +1,111 @@ +#if EFCORE6 + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Sharding.Abstractions; + +namespace ShardingCore.EFCores +{ + public class ShardingStateManager:StateManager + { + private readonly DbContext _currentDbContext; + private readonly IShardingDbContext _currentShardingDbContext; + + public ShardingStateManager(StateManagerDependencies dependencies) : base(dependencies) + { + _currentDbContext=dependencies.CurrentContext.Context; + _currentShardingDbContext = (IShardingDbContext)_currentDbContext; + } + + public override InternalEntityEntry GetOrCreateEntry(object entity) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity); + } + + public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.GetOrCreateEntry(entity,entityType); + } + + public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer); + } + + public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + } + + public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, entityType, throwOnTypeMismatch); + } + + public override int SaveChanges(bool acceptAllChangesOnSuccess) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled&&_currentDbContext.Database.CurrentTransaction==null&&_currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = _currentDbContext.Database.BeginTransaction()) + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + tran.Commit(); + } + } + else + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + } + + return i; + } + + public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled && _currentDbContext.Database.CurrentTransaction==null && _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = await _currentDbContext.Database.BeginTransactionAsync(cancellationToken)) + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + await tran.CommitAsync(cancellationToken); + } + } + else + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + } + + + return i; + } + } +} +#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingChangeTracker.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingChangeTracker.cs index 88134fa3..593f20d2 100644 --- a/src/ShardingCore/EFCores/EFCore7x/ShardingChangeTracker.cs +++ b/src/ShardingCore/EFCores/EFCore7x/ShardingChangeTracker.cs @@ -91,7 +91,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } @@ -101,7 +101,7 @@ namespace ShardingCore.EFCores { if (_dbContext is IShardingDbContext shardingDbContext) { - var genericDbContext = shardingDbContext.CreateGenericDbContext(rootEntity); + var genericDbContext = shardingDbContext.GetShardingExecutor().CreateGenericDbContext(rootEntity); genericDbContext.ChangeTracker.TrackGraph(rootEntity,state,callback); // Do(c => c.TrackGraph(rootEntity,callback)); } diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingDbSetSource.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingDbSetSource.cs deleted file mode 100644 index f7848a76..00000000 --- a/src/ShardingCore/EFCores/EFCore7x/ShardingDbSetSource.cs +++ /dev/null @@ -1,57 +0,0 @@ -#if EFCORE7 - -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; -using System; -using System.Collections.Concurrent; -using System.Reflection; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: Saturday, 14 August 2021 10:17:43 - * @Email: 326308290@qq.com - */ - public class ShardingDbSetSource : IDbSetSource - { - - private static readonly MethodInfo _genericCreateSet - = typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateSetFactory)); - - private readonly ConcurrentDictionary<(Type Type, string Name), Func> _cache - = new ConcurrentDictionary<(Type Type, string Name), Func>(); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual object Create(DbContext context, Type type) - => CreateCore(context, type, null, _genericCreateSet); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual object Create(DbContext context, string name, Type type) - => CreateCore(context, type, name, _genericCreateSet); - - private object CreateCore(DbContext context, Type type, string name, MethodInfo createMethod) - => _cache.GetOrAdd( - (type, name), - t => (Func)createMethod - .MakeGenericMethod(t.Type) - .Invoke(null, null))(context, name); - - private static Func CreateSetFactory() - where TEntity : class - => (c, name) => new ShardingInternalDbSet(c, name); - } - -} -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingInternalDbSet.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingInternalDbSet.cs deleted file mode 100644 index 73266cbc..00000000 --- a/src/ShardingCore/EFCores/EFCore7x/ShardingInternalDbSet.cs +++ /dev/null @@ -1,435 +0,0 @@ -#if EFCORE7 -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using Microsoft.EntityFrameworkCore.Internal; -using ShardingCore.Core; -using ShardingCore.Sharding.Abstractions; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Infrastructure; -using ShardingCore.Core.EntityMetadatas; -using ShardingCore.Core.RuntimeContexts; -using ShardingCore.Core.TrackerManagers; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources; -using ShardingCore.Core.VirtualRoutes.Abstractions; -using ShardingCore.Exceptions; -using ShardingCore.Extensions; -using ShardingCore.Utils; - -namespace ShardingCore.EFCores -{ - /* - * @Author: xjm - * @Description: - * @Date: 2021/8/15 8:39:15 - * @Ver: 1.0 - * @Email: 326308290@qq.com - */ - public class ShardingInternalDbSet : InternalDbSet - where TEntity : class - { - private readonly IShardingDbContext _context; - private readonly IShardingRuntimeContext _shardingRuntimeContext; - private LocalView? _localView; - - public ShardingInternalDbSet(DbContext context, string entityTypeName) : base(context, entityTypeName) - { - _context = (IShardingDbContext)context; - _shardingRuntimeContext = context.GetShardingRuntimeContext(); - } - - private IDataSourceRouteManager _dataSourceRouteManager; - - protected IDataSourceRouteManager DataSourceRouteManager - { - get - { - if (null == _dataSourceRouteManager) - { - _dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager(); - } - - return _dataSourceRouteManager; - } - } - - public override LocalView Local - { - get - { - - if (((DbContext)_context).ChangeTracker.AutoDetectChangesEnabled) - { - ((DbContext)_context).ChangeTracker.DetectChanges(); - } - - return _localView ??= new ShardingLocalView(this); - } - } - private ITableRouteManager _tableRouteManager; - - protected ITableRouteManager TableRouteManager - { - get - { - if (null == _tableRouteManager) - { - _tableRouteManager = _shardingRuntimeContext.GetTableRouteManager(); - } - - return _tableRouteManager; - } - } - - private IEntityMetadataManager _entityMetadataManager; - - protected IEntityMetadataManager EntityMetadataManager - { - get - { - if (null == _entityMetadataManager) - { - _entityMetadataManager = _shardingRuntimeContext.GetEntityMetadataManager(); - } - - return _entityMetadataManager; - } - } - - private ITrackerManager _trackerManager; - - protected ITrackerManager TrackerManager - { - get - { - if (null == _trackerManager) - { - _trackerManager = _shardingRuntimeContext.GetTrackerManager(); - } - - return _trackerManager; - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Add(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Add(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async ValueTask> AddAsync( - TEntity entity, - CancellationToken cancellationToken = default) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return await genericDbContext.Set().AddAsync(entity, cancellationToken); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Attach(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Attach(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Remove(TEntity entity) - { - Check.NotNull(entity, nameof(entity)); - - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Remove(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override EntityEntry Update(TEntity entity) - { - var genericDbContext = _context.CreateGenericDbContext(entity); - return genericDbContext.Set().Update(entity); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(params TEntity[] entities) - { - Check.NotNull(entities, nameof(entities)); - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(params TEntity[] entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AddRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AddRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override async Task AddRangeAsync( - IEnumerable entities, - CancellationToken cancellationToken = default) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.Set().AddRangeAsync(aggregateKv.Value, cancellationToken); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void AttachRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().AttachRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void RemoveRange(IEnumerable entities) - { - Check.NotNull(entities, nameof(entities)); - - - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().RemoveRange(aggregateKv.Value); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void UpdateRange(IEnumerable entities) - { - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.Set().UpdateRange(aggregateKv.Value); - } - } - - private Dictionary> AggregateToDic(IEnumerable entities) - { - return entities.Select(o => - { - var dbContext = _context.CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext).ToDictionary(o => o.Key, o => o.Select(g => g.Entity)); - } - - public override TEntity Find(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().Find(keyValues); - } - - return base.Find(keyValues); - } - - public override ValueTask FindAsync(params object[] keyValues) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues); - } - - return base.FindAsync(keyValues); - } - - public override ValueTask FindAsync(object[] keyValues, CancellationToken cancellationToken) - { - var primaryKeyFindDbContext = GetDbContextByKeyValue(keyValues); - if (primaryKeyFindDbContext != null) - { - return primaryKeyFindDbContext.Set().FindAsync(keyValues, cancellationToken); - } - - return base.FindAsync(keyValues, cancellationToken); - } - - private DbContext GetDbContextByKeyValue(params object[] keyValues) - { - var entityMetadata = EntityMetadataManager.TryGet(typeof(TEntity)); - if (entityMetadata == null) - { - throw new ShardingCoreInvalidOperationException( - $"cant found type:[{typeof(TEntity)}] in {nameof(IEntityMetadataManager)}"); - } - - //既不是分表也不是分库的话就是默认对象 - if (!entityMetadata.IsShardingTable() && !entityMetadata.IsShardingDataSource()) - { - var defaultDataSourceName = _shardingRuntimeContext.GetVirtualDataSource().DefaultDataSourceName; - var routeTailFactory = _shardingRuntimeContext.GetRouteTailFactory(); - var routeTail = routeTailFactory.Create(string.Empty); - return _context.GetShareDbContext(defaultDataSourceName, routeTail); - } - - if (keyValues.Length == 1) - { - //单key字段 - if (entityMetadata.IsSingleKey) - { - var isShardingDataSource = entityMetadata.IsShardingDataSource(); - var shardingDataSourceFieldIsKey = entityMetadata.ShardingDataSourceFieldIsKey(); - if (isShardingDataSource && !shardingDataSourceFieldIsKey) - return null; - var isShardingTable = entityMetadata.IsShardingTable(); - var shardingTableFieldIsKey = entityMetadata.ShardingTableFieldIsKey(); - if (isShardingTable && !shardingTableFieldIsKey) - return null; - var primaryKeyValue = keyValues[0]; - if (primaryKeyValue != null) - { - var dataSourceName = GetDataSourceName(primaryKeyValue); - var realEntityType = TrackerManager.TranslateEntityType(typeof(TEntity)); - var tableTail = TableRouteManager.GetTableTail(dataSourceName, primaryKeyValue,realEntityType); - var routeTail = _shardingRuntimeContext.GetRouteTailFactory().Create(tableTail); - return _context.GetShareDbContext(dataSourceName, routeTail); - } - } - } - - return null; - } - - private string GetDataSourceName(object shardingKeyValue) - { - return DataSourceRouteManager.GetDataSourceName(shardingKeyValue); - } - } -} - -#endif \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs index f0d927d1..474808e0 100644 --- a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs +++ b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs @@ -1,24 +1,32 @@ +#if EFCORE7 + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage; using ShardingCore.Sharding.Abstractions; namespace ShardingCore.EFCores { public class ShardingStateManager:StateManager { + private readonly DbContext _currentDbContext; private readonly IShardingDbContext _currentShardingDbContext; public ShardingStateManager(StateManagerDependencies dependencies) : base(dependencies) { - - _currentShardingDbContext = (IShardingDbContext)dependencies.CurrentContext; + _currentDbContext=dependencies.CurrentContext.Context; + _currentShardingDbContext = (IShardingDbContext)_currentDbContext; } public override InternalEntityEntry GetOrCreateEntry(object entity) { - var genericDbContext = _currentShardingDbContext.CreateGenericDbContext(entity); + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); var dbContextDependencies = genericDbContext.GetService(); var stateManager = dbContextDependencies.StateManager; return stateManager.GetOrCreateEntry(entity); @@ -26,10 +34,78 @@ namespace ShardingCore.EFCores public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) { - var genericDbContext = _currentShardingDbContext.CreateGenericDbContext(entity); + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); var dbContextDependencies = genericDbContext.GetService(); var stateManager = dbContextDependencies.StateManager; return stateManager.GetOrCreateEntry(entity,entityType); } + + public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer); + } + + public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + } + + public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) + { + var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var dbContextDependencies = genericDbContext.GetService(); + var stateManager = dbContextDependencies.StateManager; + return stateManager.TryGetEntry(entity, entityType, throwOnTypeMismatch); + } + + public override int SaveChanges(bool acceptAllChangesOnSuccess) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled&&_currentDbContext.Database.CurrentTransaction==null&&_currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = _currentDbContext.Database.BeginTransaction()) + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + tran.Commit(); + } + } + else + { + i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); + } + + return i; + } + + public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) + { + //ApplyShardingConcepts(); + int i = 0; + //如果是内部开的事务就内部自己消化 + if (_currentDbContext.Database.AutoTransactionsEnabled && _currentDbContext.Database.CurrentTransaction==null && _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + { + using (var tran = await _currentDbContext.Database.BeginTransactionAsync(cancellationToken)) + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + await tran.CommitAsync(cancellationToken); + } + } + else + { + i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); + } + + + return i; + } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore.cs b/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore.cs index fb7d2c0b..b23c54aa 100644 --- a/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore.cs +++ b/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore.cs @@ -146,7 +146,7 @@ namespace ShardingCore.Extensions var shardingRuntimeContext = dbContext.GetShardingRuntimeContext(); var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager(); -#if EFCORE6 +#if EFCORE6 || EFCORE7 var entityTypes = contextModel.GetEntityTypes(); foreach (var entityType in entityTypes) { @@ -156,8 +156,17 @@ namespace ShardingCore.Extensions } } var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel; + foreach (var keyValuePair in contextModelRelationalModel.Tables) + { + foreach (var valueEntityTypeMapping in keyValuePair.Value.EntityTypeMappings) + { + var x = !entityMetadataManager.IsOnlyShardingDataSource(valueEntityTypeMapping.EntityType.ClrType); + Console.WriteLine(valueEntityTypeMapping.EntityType.ClrType); + Console.WriteLine(x); + } + } var valueTuples = - contextModelRelationalModel.Tables.Where(o => o.Value.EntityTypeMappings.Any(m => !entityMetadataManager.IsShardingDataSource(m.EntityType.ClrType) ||entityMetadataManager.TryGet(m.EntityType.ClrType)==null)).Select(o => o.Key).ToList(); + contextModelRelationalModel.Tables.Where(o => o.Value.EntityTypeMappings.Any(m => !entityMetadataManager.IsOnlyShardingDataSource(m.EntityType.ClrType)) ).Select(o => o.Key).ToList(); for (int i = 0; i < valueTuples.Count; i++) { contextModelRelationalModel.Tables.Remove(valueTuples[i]); @@ -174,7 +183,7 @@ namespace ShardingCore.Extensions } var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel; var valueTuples = - contextModelRelationalModel.Tables.Where(o => o.Value.EntityTypeMappings.Any(m => !entityMetadataManager.IsShardingDataSource(m.EntityType.ClrType)||entityMetadataManager.TryGet(m.EntityType.ClrType)==null)).Select(o => o.Key).ToList(); + contextModelRelationalModel.Tables.Where(o => o.Value.EntityTypeMappings.Any(m => !entityMetadataManager.IsOnlyShardingDataSource(m.EntityType.ClrType))).Select(o => o.Key).ToList(); for (int i = 0; i < valueTuples.Count; i++) { contextModelRelationalModel.Tables.Remove(valueTuples[i]); @@ -191,7 +200,7 @@ namespace ShardingCore.Extensions _data.Clear(); } } - var list = entityTypes.Where(o => !entityMetadataManager.IsShardingDataSource(o.Value.ClrType) || entityMetadataManager.TryGet(o.Value.ClrType) == null).Select(o => o.Key).ToList(); + var list = entityTypes.Where(o => !entityMetadataManager.IsOnlyShardingDataSource(o.Value.ClrType)).Select(o => o.Key).ToList(); for (int i = 0; i < list.Count; i++) { entityTypes.Remove(list[i]); @@ -216,7 +225,7 @@ namespace ShardingCore.Extensions var contextModel = dbContext.Model as Model; #endif -#if EFCORE6 +#if EFCORE6 || EFCORE7 var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel; contextModelRelationalModel.Tables.Clear(); #endif diff --git a/src/ShardingCore/Extensions/ShardingDbContextExtension.cs b/src/ShardingCore/Extensions/ShardingDbContextExtension.cs index 0eae4f4f..19471a8c 100644 --- a/src/ShardingCore/Extensions/ShardingDbContextExtension.cs +++ b/src/ShardingCore/Extensions/ShardingDbContextExtension.cs @@ -39,7 +39,7 @@ namespace ShardingCore.Extensions /// public static DbContext GetShareDbContext(this IShardingDbContext shardingDbContext,string dataSourceName,IRouteTail routeTail) { - return shardingDbContext.GetDbContext(dataSourceName, CreateDbContextStrategyEnum.ShareConnection, routeTail); + return shardingDbContext.GetShardingExecutor().CreateDbContext(CreateDbContextStrategyEnum.ShareConnection,dataSourceName, routeTail); } /// @@ -51,7 +51,7 @@ namespace ShardingCore.Extensions /// public static DbContext GetIndependentWriteDbContext(this IShardingDbContext shardingDbContext,string dataSourceName,IRouteTail routeTail) { - return shardingDbContext.GetDbContext(dataSourceName, CreateDbContextStrategyEnum.IndependentConnectionWrite, routeTail); + return shardingDbContext.GetShardingExecutor().CreateDbContext(CreateDbContextStrategyEnum.IndependentConnectionWrite,dataSourceName, routeTail); } /// /// 获取独立生命周期的读连接字符串的db context @@ -62,7 +62,7 @@ namespace ShardingCore.Extensions /// public static DbContext GetIndependentQueryDbContext(this IShardingDbContext shardingDbContext,string dataSourceName,IRouteTail routeTail) { - return shardingDbContext.GetDbContext(dataSourceName, CreateDbContextStrategyEnum.IndependentConnectionQuery, routeTail); + return shardingDbContext.GetShardingExecutor().CreateDbContext(CreateDbContextStrategyEnum.IndependentConnectionQuery,dataSourceName, routeTail); } } } diff --git a/src/ShardingCore/Extensions/ShardingExtension.cs b/src/ShardingCore/Extensions/ShardingExtension.cs index a88d721a..671fb731 100644 --- a/src/ShardingCore/Extensions/ShardingExtension.cs +++ b/src/ShardingCore/Extensions/ShardingExtension.cs @@ -108,7 +108,7 @@ namespace ShardingCore.Extensions new Dictionary>() { { - shardingDbContext.CreateGenericDbContext(entitiesArray[0]), + shardingDbContext.GetShardingExecutor().CreateGenericDbContext(entitiesArray[0]), entitiesArray } } diff --git a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs index b9c8718f..f4dfd923 100644 --- a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs +++ b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs @@ -33,381 +33,28 @@ namespace ShardingCore.Sharding { ShardingDbContextExecutor = new ShardingDbContextExecutor(this); } - - IsExecutor = wrapOptionsExtension == null; } - - /// - /// 是否是真正的执行者 - /// - public bool IsExecutor { get; } - - - - public DbContext GetDbContext(string dataSourceName, CreateDbContextStrategyEnum strategy, IRouteTail routeTail) - { - return ShardingDbContextExecutor.CreateDbContext(strategy, dataSourceName, routeTail); - } - - /// - /// 根据对象创建通用的dbcontext - /// - /// - /// - /// - public DbContext CreateGenericDbContext(TEntity entity) where TEntity : class - { - return ShardingDbContextExecutor.CreateGenericDbContext(entity); - } - + public IShardingDbContextExecutor GetShardingExecutor() { return ShardingDbContextExecutor; } - - public override EntityEntry Add(object entity) - { - if (IsExecutor) - base.Add(entity); - return CreateGenericDbContext(entity).Add(entity); - } - - public override EntityEntry Add(TEntity entity) - { - if (IsExecutor) - return base.Add(entity); - return CreateGenericDbContext(entity).Add(entity); - } - - - -#if !EFCORE2 - - public override ValueTask> AddAsync(TEntity entity, CancellationToken cancellationToken = new CancellationToken()) - { - if (IsExecutor) - return base.AddAsync(entity, cancellationToken); - return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken); - } - - public override ValueTask AddAsync(object entity, CancellationToken cancellationToken = new CancellationToken()) - { - if (IsExecutor) - return base.AddAsync(entity, cancellationToken); - return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken); - } -#endif -#if EFCORE2 - public override Task> AddAsync(TEntity entity, CancellationToken cancellationToken = new CancellationToken()) - { - if (IsExecutor) - return base.AddAsync(entity, cancellationToken); - return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken); - } - - public override Task AddAsync(object entity, CancellationToken cancellationToken = new CancellationToken()) - { - if (IsExecutor) - return base.AddAsync(entity, cancellationToken); - return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken); - } -#endif - - private Dictionary> AggregateToDic(IEnumerable entities) where TEntity:class - { - return entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext).ToDictionary(o => o.Key, o => o.Select(g => g.Entity)); - } - public override void AddRange(params object[] entities) - { - if (IsExecutor) - { - base.AddRange(entities); - return; - } - - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.AddRange(aggregateKv.Value); - } - } - - public override void AddRange(IEnumerable entities) - { - if (IsExecutor) - { - base.AddRange(entities); - return; - } - - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.AddRange(aggregateKv.Value); - } - } - - public override async Task AddRangeAsync(params object[] entities) - { - if (IsExecutor) - { - await base.AddRangeAsync(entities); - return; - } - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.AddRangeAsync(aggregateKv.Value); - } - } - - public override async Task AddRangeAsync(IEnumerable entities, CancellationToken cancellationToken = new CancellationToken()) - { - if (IsExecutor) - { - await base.AddRangeAsync(entities, cancellationToken); - return; - } - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - await aggregateKv.Key.AddRangeAsync(aggregateKv.Value,cancellationToken); - } - } - - public override EntityEntry Attach(TEntity entity) - { - if (IsExecutor) - return base.Attach(entity); - return CreateGenericDbContext(entity).Attach(entity); - } - - public override EntityEntry Attach(object entity) - { - if (IsExecutor) - return base.Attach(entity); - return CreateGenericDbContext(entity).Attach(entity); - } - - public override void AttachRange(params object[] entities) - { - if (IsExecutor) - { - base.AttachRange(entities); - return; - } - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.AttachRange(aggregateKv.Value); - } - } - - public override void AttachRange(IEnumerable entities) - { - if (IsExecutor) - { - base.AttachRange(entities); - return; - } - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.AttachRange(aggregateKv.Value); - } - } - - - //public override DatabaseFacade Database => _dbContextCaches.Any() - // ? _dbContextCaches.First().Value.Database - // : GetDbContext(true, string.Empty).Database; - - public override EntityEntry Entry(TEntity entity) - { - if (IsExecutor) - return base.Entry(entity); - return CreateGenericDbContext(entity).Entry(entity); - } - - public override EntityEntry Entry(object entity) - { - if (IsExecutor) - return base.Entry(entity); - return CreateGenericDbContext(entity).Entry(entity); - } - - public override EntityEntry Update(TEntity entity) - { - if (IsExecutor) - return base.Update(entity); - return CreateGenericDbContext(entity).Update(entity); - } - - public override EntityEntry Update(object entity) - { - if (IsExecutor) - return base.Update(entity); - return CreateGenericDbContext(entity).Update(entity); - } - - public override void UpdateRange(params object[] entities) - { - if (IsExecutor) - { - base.UpdateRange(entities); - return; - } - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.UpdateRange(aggregateKv.Value); - } - } - - public override void UpdateRange(IEnumerable entities) - { - if (IsExecutor) - { - base.UpdateRange(entities); - return; - } - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.UpdateRange(aggregateKv.Value); - } - } - - public override EntityEntry Remove(TEntity entity) - { - if (IsExecutor) - return base.Remove(entity); - return CreateGenericDbContext(entity).Remove(entity); - } - - public override EntityEntry Remove(object entity) - { - if (IsExecutor) - return base.Remove(entity); - return CreateGenericDbContext(entity).Remove(entity); - } - - public override void RemoveRange(params object[] entities) - { - if (IsExecutor) - { - base.RemoveRange(entities); - return; - } - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.RemoveRange(aggregateKv.Value); - } - } - - public override void RemoveRange(IEnumerable entities) - { - if (IsExecutor) - { - base.RemoveRange(entities); - return; - } - var aggregateToDic = AggregateToDic(entities); - foreach (var aggregateKv in aggregateToDic) - { - aggregateKv.Key.RemoveRange(aggregateKv.Value); - } - } - - public override int SaveChanges(bool acceptAllChangesOnSuccess) - { - if (IsExecutor) - return base.SaveChanges(acceptAllChangesOnSuccess); - //ApplyShardingConcepts(); - int i = 0; - //如果是内部开的事务就内部自己消化 - if (Database.AutoTransactionsEnabled&&Database.CurrentTransaction==null&&ShardingDbContextExecutor.IsMultiDbContext) - { - using (var tran = Database.BeginTransaction()) - { - i = ShardingDbContextExecutor.SaveChanges(acceptAllChangesOnSuccess); - tran.Commit(); - } - } - else - { - i = ShardingDbContextExecutor.SaveChanges(acceptAllChangesOnSuccess); - } - - return i; - } - - - public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) - { - if (IsExecutor) - return await base.SaveChangesAsync(acceptAllChangesOnSuccess,cancellationToken); - //ApplyShardingConcepts(); - int i = 0; - //如果是内部开的事务就内部自己消化 - if (Database.AutoTransactionsEnabled && Database.CurrentTransaction==null && ShardingDbContextExecutor.IsMultiDbContext) - { - using (var tran = await Database.BeginTransactionAsync(cancellationToken)) - { - i = await ShardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); -#if EFCORE2 - tran.Commit(); -#endif -#if !EFCORE2 - await tran.CommitAsync(cancellationToken); -#endif - } - } - else - { - i = await ShardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - } - - - return i; - } public override void Dispose() { - - if (IsExecutor) - { - base.Dispose(); - } - else - { - ShardingDbContextExecutor.Dispose(); - base.Dispose(); - } + ShardingDbContextExecutor?.Dispose(); + base.Dispose(); } #if !EFCORE2 public override async ValueTask DisposeAsync() { - if (IsExecutor) - { - await base.DisposeAsync(); - } - else + if (ShardingDbContextExecutor!=null) { await ShardingDbContextExecutor.DisposeAsync(); - - await base.DisposeAsync(); } + + await base.DisposeAsync(); } #endif } diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs index 62266bc7..e86e2313 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingDbContext.cs @@ -13,23 +13,6 @@ namespace ShardingCore.Sharding.Abstractions */ public interface IShardingDbContext { - /// - /// create DbContext - /// - /// data source - /// 生成db connection的策略,主要区别在于是否和主db connection一直或者是否需要缓存其connection还有是否是独立声明周期的区别 - /// - /// - DbContext GetDbContext(string dataSourceName, CreateDbContextStrategyEnum strategy, IRouteTail routeTail); - - /// - /// 创建通用的db context - /// - /// - /// - /// - DbContext CreateGenericDbContext(T entity) where T : class; - IShardingDbContextExecutor GetShardingExecutor(); diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs b/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs index 4a20745d..af262436 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs @@ -52,5 +52,7 @@ namespace ShardingCore.Sharding.Abstractions int SaveChanges(bool acceptAllChangesOnSuccess); + DbContext GetShellDbContext(); + } } diff --git a/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs b/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs index cf8a1963..d02f8703 100644 --- a/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs +++ b/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs @@ -190,6 +190,11 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors return i; } + public DbContext GetShellDbContext() + { + return _shardingDbContext; + } + public void NotifyShardingTransaction() { foreach (var dbContextCache in _dbContextCaches) @@ -355,5 +360,7 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors } } } + + } } \ No newline at end of file diff --git a/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs b/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs index 0483e4cf..35f4fe6c 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs @@ -191,7 +191,7 @@ namespace ShardingCore.Sharding.ShardingExecutors var strategy = !IsParallelQuery() ? CreateDbContextStrategyEnum.ShareConnection : CreateDbContextStrategyEnum.IndependentConnectionQuery; - var dbContext = GetShardingDbContext().GetDbContext(sqlRouteUnit.DataSourceName,strategy , routeTailFactory.Create(sqlRouteUnit.TableRouteResult)); + var dbContext = GetShardingDbContext().GetShardingExecutor().CreateDbContext(strategy,sqlRouteUnit.DataSourceName, routeTailFactory.Create(sqlRouteUnit.TableRouteResult)); _queryCompilerExecutor = new QueryCompilerExecutor(dbContext, GetQueryExpression()); } } diff --git a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs index 5a24c79e..4459c861 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContext.cs @@ -175,7 +175,7 @@ namespace ShardingCore.Sharding.ShardingExecutors var strategy = !IsParallelQuery() ? CreateDbContextStrategyEnum.ShareConnection : CreateDbContextStrategyEnum.IndependentConnectionQuery; - var dbContext = _shardingDbContext.GetDbContext(virtualDataSource.DefaultDataSourceName, strategy, routeTailFactory.Create(string.Empty)); + var dbContext = _shardingDbContext.GetShardingExecutor().CreateDbContext(strategy,virtualDataSource.DefaultDataSourceName, routeTailFactory.Create(string.Empty)); _queryCompilerExecutor = new QueryCompilerExecutor(dbContext, _queryExpression); } } diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index 30a783df..f85ba0d5 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -128,7 +128,7 @@ namespace ShardingCore.Sharding { var routeTail = _routeTailFactory.Create(sqlRouteUnit.TableRouteResult); - var dbContext = GetShardingDbContext().GetDbContext(sqlRouteUnit.DataSourceName, CreateDbContextStrategyEnum.IndependentConnectionQuery, routeTail); + var dbContext = GetShardingDbContext().GetShardingExecutor().CreateDbContext(CreateDbContextStrategyEnum.IndependentConnectionQuery,sqlRouteUnit.DataSourceName, routeTail); _parallelDbContexts.TryAdd(dbContext, null); return dbContext; diff --git a/src/ShardingCore/ShardingCoreExtension.cs b/src/ShardingCore/ShardingCoreExtension.cs index b194a0bf..31277bb8 100644 --- a/src/ShardingCore/ShardingCoreExtension.cs +++ b/src/ShardingCore/ShardingCoreExtension.cs @@ -214,11 +214,13 @@ namespace ShardingCore this DbContextOptionsBuilder optionsBuilder, IShardingRuntimeContext shardingRuntimeContext) { return optionsBuilder.UseShardingWrapMark().UseShardingOptions(shardingRuntimeContext) - .ReplaceService() + // .ReplaceService() .ReplaceService() .ReplaceService() .ReplaceService() + .ReplaceService() .ReplaceService(); } diff --git a/src6/ShardingCore6/ShardingCore6.csproj b/src6/ShardingCore6/ShardingCore6.csproj index 7386a7c0..5d770f9d 100644 --- a/src6/ShardingCore6/ShardingCore6.csproj +++ b/src6/ShardingCore6/ShardingCore6.csproj @@ -27,6 +27,9 @@ + + EFCores\EFCore6x\ShardingStateManager.cs + From 96e785ac107c8726dce2c0608c4199eb2f7c24f3 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Fri, 23 Dec 2022 09:10:01 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0aop=E9=92=88=E5=AF=B9ab?= =?UTF-8?q?pvnext=E7=9A=84=E5=A4=84=E7=90=86[#226]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyShardingExtension.cs | 2 +- .../AbstractShardingAbpDbContext.cs | 460 +----------------- .../EFCores/EFCore7x/ShardingStateManager.cs | 12 +- .../IShardingDbContextExecutor.cs | 16 + .../ShardingDbContextExecutorEventArgs.cs | 55 +++ .../ShardingDbContextExecutor.cs | 38 +- 6 files changed, 131 insertions(+), 452 deletions(-) create mode 100644 src/ShardingCore/Sharding/Abstractions/ShardingDbContextExecutorEventArgs.cs diff --git a/samples/Sample.AutoCreateIfPresent/MyShardingExtension.cs b/samples/Sample.AutoCreateIfPresent/MyShardingExtension.cs index 07595869..47d54649 100644 --- a/samples/Sample.AutoCreateIfPresent/MyShardingExtension.cs +++ b/samples/Sample.AutoCreateIfPresent/MyShardingExtension.cs @@ -44,7 +44,7 @@ public static class MyShardingExtension new Dictionary>() { { - shardingDbContext.CreateGenericDbContext(entitiesArray[0]), + shardingDbContext.GetShardingExecutor().CreateGenericDbContext(entitiesArray[0]), entitiesArray } } diff --git a/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs b/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs index 27907862..89eb4735 100644 --- a/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs +++ b/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs @@ -34,48 +34,25 @@ namespace Samples.AbpSharding if (wrapOptionsExtension != null) { _shardingDbContextExecutor = new ShardingDbContextExecutor(this); + _shardingDbContextExecutor.EntityCreateDbContextBefore += (sender, args) => + { + CheckAndSetShardingKeyThatSupportAutoCreate(args.Entity); + }; + _shardingDbContextExecutor.CreateDbContextAfter += (sender, args) => + { + var shardingDbContextExecutor = (IShardingDbContextExecutor)sender; + var argsDbContext = args.DbContext; + var shellDbContext = shardingDbContextExecutor.GetShellDbContext(); + + if (argsDbContext is AbpDbContext abpDbContext&&shellDbContext is AbpDbContext abpShellDbContext && + abpDbContext.LazyServiceProvider == null) + { + abpDbContext.LazyServiceProvider = abpShellDbContext.LazyServiceProvider; + } + }; } } - /// - /// 是否是真正的执行者 - /// - private bool isExecutor => _shardingDbContextExecutor == null; - - //public void ShardingUpgrade() - //{ - // //IsExecutor = true; - //} - - public DbContext GetDbContext(string dataSourceName, CreateDbContextStrategyEnum strategy, IRouteTail routeTail) - { - var dbContext = _shardingDbContextExecutor.CreateDbContext(strategy, dataSourceName, routeTail); - if (dbContext is AbpDbContext abpDbContext) - { - abpDbContext.LazyServiceProvider = this.LazyServiceProvider; - } - - return dbContext; - } - - /// - /// 根据对象创建通用的dbcontext - /// - /// - /// - /// - public DbContext CreateGenericDbContext(TEntity entity) where TEntity : class - { - CheckAndSetShardingKeyThatSupportAutoCreate(entity); - var dbContext = _shardingDbContextExecutor.CreateGenericDbContext(entity); - if (dbContext is AbpDbContext abpDbContext && abpDbContext.LazyServiceProvider == null) - { - abpDbContext.LazyServiceProvider = this.LazyServiceProvider; - } - - return dbContext; - } - public IShardingDbContextExecutor GetShardingExecutor() { return _shardingDbContextExecutor; @@ -118,416 +95,19 @@ namespace Samples.AbpSharding } } - - public override EntityEntry Add(object entity) - { - if (isExecutor) - base.Add(entity); - return CreateGenericDbContext(entity).Add(entity); - } - - public override EntityEntry Add(TEntity entity) - { - if (isExecutor) - return base.Add(entity); - return CreateGenericDbContext(entity).Add(entity); - } - - - public override ValueTask> AddAsync(TEntity entity, CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - return base.AddAsync(entity, cancellationToken); - return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken); - } - - public override ValueTask AddAsync(object entity, CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - return base.AddAsync(entity, cancellationToken); - return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken); - } - - public override void AddRange(params object[] entities) - { - if (isExecutor) - { - base.AddRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.AddRange(group.Select(o => o.Entity)); - } - } - public override void AddRange(IEnumerable entities) - { - if (isExecutor) - { - base.AddRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.AddRange(group.Select(o => o.Entity)); - } - } - - public override async Task AddRangeAsync(params object[] entities) - { - if (isExecutor) - { - await base.AddRangeAsync(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - await group.Key.AddRangeAsync(group.Select(o => o.Entity)); - } - } - - public override async Task AddRangeAsync(IEnumerable entities, CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - { - await base.AddRangeAsync(entities, cancellationToken); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - await group.Key.AddRangeAsync(group.Select(o => o.Entity)); - } - } - - public override EntityEntry Attach(TEntity entity) - { - if (isExecutor) - return base.Attach(entity); - return CreateGenericDbContext(entity).Attach(entity); - } - - public override EntityEntry Attach(object entity) - { - if (isExecutor) - return base.Attach(entity); - return CreateGenericDbContext(entity).Attach(entity); - } - - public override void AttachRange(params object[] entities) - { - if (isExecutor) - { - base.AttachRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.AttachRange(group.Select(o => o.Entity)); - } - } - - public override void AttachRange(IEnumerable entities) - { - if (isExecutor) - { - base.AttachRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.AttachRange(group.Select(o => o.Entity)); - } - } - - - //public override DatabaseFacade Database => _dbContextCaches.Any() - // ? _dbContextCaches.First().Value.Database - // : GetDbContext(true, string.Empty).Database; - - public override EntityEntry Entry(TEntity entity) - { - if (isExecutor) - return base.Entry(entity); - return CreateGenericDbContext(entity).Entry(entity); - } - - public override EntityEntry Entry(object entity) - { - if (isExecutor) - return base.Entry(entity); - return CreateGenericDbContext(entity).Entry(entity); - } - - public override EntityEntry Update(TEntity entity) - { - if (isExecutor) - return base.Update(entity); - return CreateGenericDbContext(entity).Update(entity); - } - - public override EntityEntry Update(object entity) - { - if (isExecutor) - return base.Update(entity); - return CreateGenericDbContext(entity).Update(entity); - } - - public override void UpdateRange(params object[] entities) - { - if (isExecutor) - { - base.UpdateRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.UpdateRange(group.Select(o => o.Entity)); - } - } - - public override void UpdateRange(IEnumerable entities) - { - if (isExecutor) - { - base.UpdateRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.UpdateRange(group.Select(o => o.Entity)); - } - } - - public override EntityEntry Remove(TEntity entity) - { - if (isExecutor) - return base.Remove(entity); - return CreateGenericDbContext(entity).Remove(entity); - } - - public override EntityEntry Remove(object entity) - { - if (isExecutor) - return base.Remove(entity); - return CreateGenericDbContext(entity).Remove(entity); - } - - public override void RemoveRange(params object[] entities) - { - if (isExecutor) - { - base.RemoveRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.RemoveRange(group.Select(o => o.Entity)); - } - } - - public override void RemoveRange(IEnumerable entities) - { - if (isExecutor) - { - base.RemoveRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.RemoveRange(group.Select(o => o.Entity)); - } - } - - public override int SaveChanges() - { - - if (isExecutor) - return base.SaveChanges(); - return this.SaveChanges(true); - } - - public override int SaveChanges(bool acceptAllChangesOnSuccess) - { - if (isExecutor) - return base.SaveChanges(acceptAllChangesOnSuccess); - //ApplyShardingConcepts(); - int i = 0; - //如果是内部开的事务就内部自己消化 - if (Database.CurrentTransaction == null && _shardingDbContextExecutor.IsMultiDbContext) - { - using (var tran = Database.BeginTransaction()) - { - i = _shardingDbContextExecutor.SaveChanges(acceptAllChangesOnSuccess); - tran.Commit(); - } - } - else - { - i = _shardingDbContextExecutor.SaveChanges(acceptAllChangesOnSuccess); - } - - return i; - } - - - public override Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - return base.SaveChangesAsync(cancellationToken); - return this.SaveChangesAsync(true, cancellationToken); - } - - public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - //ApplyShardingConcepts(); - int i = 0; - //如果是内部开的事务就内部自己消化 - if (Database.CurrentTransaction == null && _shardingDbContextExecutor.IsMultiDbContext) - { - using (var tran = await Database.BeginTransactionAsync(cancellationToken)) - { - i = await _shardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - - await tran.CommitAsync(cancellationToken); - } - } - else - { - i = await _shardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - } - - - return i; - } - public override void Dispose() { - - if (isExecutor) - { - base.Dispose(); - } - else - { - _shardingDbContextExecutor.Dispose(); - base.Dispose(); - } + _shardingDbContextExecutor?.Dispose(); + base.Dispose(); } public override async ValueTask DisposeAsync() { - if (isExecutor) - { - await base.DisposeAsync(); - } - else + if (_shardingDbContextExecutor != null) { await _shardingDbContextExecutor.DisposeAsync(); - - await base.DisposeAsync(); } + await base.DisposeAsync(); } } } \ No newline at end of file diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs index 474808e0..154d9a8f 100644 --- a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs +++ b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs @@ -15,13 +15,11 @@ namespace ShardingCore.EFCores { public class ShardingStateManager:StateManager { - private readonly DbContext _currentDbContext; private readonly IShardingDbContext _currentShardingDbContext; public ShardingStateManager(StateManagerDependencies dependencies) : base(dependencies) { - _currentDbContext=dependencies.CurrentContext.Context; - _currentShardingDbContext = (IShardingDbContext)_currentDbContext; + _currentShardingDbContext = (IShardingDbContext)Context; } public override InternalEntityEntry GetOrCreateEntry(object entity) @@ -69,9 +67,9 @@ namespace ShardingCore.EFCores //ApplyShardingConcepts(); int i = 0; //如果是内部开的事务就内部自己消化 - if (_currentDbContext.Database.AutoTransactionsEnabled&&_currentDbContext.Database.CurrentTransaction==null&&_currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + if (Context.Database.AutoTransactionsEnabled&&Context.Database.CurrentTransaction==null&&_currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) { - using (var tran = _currentDbContext.Database.BeginTransaction()) + using (var tran = Context.Database.BeginTransaction()) { i = _currentShardingDbContext.GetShardingExecutor().SaveChanges(acceptAllChangesOnSuccess); tran.Commit(); @@ -90,9 +88,9 @@ namespace ShardingCore.EFCores //ApplyShardingConcepts(); int i = 0; //如果是内部开的事务就内部自己消化 - if (_currentDbContext.Database.AutoTransactionsEnabled && _currentDbContext.Database.CurrentTransaction==null && _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) + if (Context.Database.AutoTransactionsEnabled && Context.Database.CurrentTransaction==null && _currentShardingDbContext.GetShardingExecutor().IsMultiDbContext) { - using (var tran = await _currentDbContext.Database.BeginTransactionAsync(cancellationToken)) + using (var tran = await Context.Database.BeginTransactionAsync(cancellationToken)) { i = await _currentShardingDbContext.GetShardingExecutor().SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); await tran.CommitAsync(cancellationToken); diff --git a/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs b/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs index af262436..67add0b9 100644 --- a/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs +++ b/src/ShardingCore/Sharding/Abstractions/IShardingDbContextExecutor.cs @@ -23,6 +23,22 @@ namespace ShardingCore.Sharding.Abstractions #endif { + /// + /// 使用对象创建db context的前执行 + /// + event EventHandler EntityCreateDbContextBefore; + /// + /// 使用对象创建db context的后执行 + /// + event EventHandler EntityCreateDbContextAfter; + /// + /// 使用tail创建db context的前执行 + /// + event EventHandler CreateDbContextBefore; + /// + /// 使用tail创建db context的后执行 + /// + event EventHandler CreateDbContextAfter; /// /// has multi db context /// diff --git a/src/ShardingCore/Sharding/Abstractions/ShardingDbContextExecutorEventArgs.cs b/src/ShardingCore/Sharding/Abstractions/ShardingDbContextExecutorEventArgs.cs new file mode 100644 index 00000000..37e12b59 --- /dev/null +++ b/src/ShardingCore/Sharding/Abstractions/ShardingDbContextExecutorEventArgs.cs @@ -0,0 +1,55 @@ +using System; +using Microsoft.EntityFrameworkCore; +using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; + +namespace ShardingCore.Sharding.Abstractions +{ + public class EntityCreateDbContextBeforeEventArgs: EventArgs + { + public object Entity { get; } + + public EntityCreateDbContextBeforeEventArgs(object entity) + { + Entity = entity; + } + } + public class CreateDbContextBeforeEventArgs: EventArgs + { + public CreateDbContextStrategyEnum Strategy { get; } + public string DataSourceName { get; } + public IRouteTail RouteTail { get; } + + public CreateDbContextBeforeEventArgs(CreateDbContextStrategyEnum strategy, string dataSourceName, IRouteTail routeTail) + { + Strategy = strategy; + DataSourceName = dataSourceName; + RouteTail = routeTail; + } + } + public class CreateDbContextAfterEventArgs: EventArgs + { + public CreateDbContextStrategyEnum Strategy { get; } + public string DataSourceName { get; } + public IRouteTail RouteTail { get; } + public DbContext DbContext { get; } + + public CreateDbContextAfterEventArgs(CreateDbContextStrategyEnum strategy, string dataSourceName, IRouteTail routeTail,DbContext dbContext) + { + Strategy = strategy; + DataSourceName = dataSourceName; + RouteTail = routeTail; + DbContext = dbContext; + } + } + public class EntityCreateDbContextAfterEventArgs: EventArgs + { + public object Entity { get; } + public DbContext DbContext { get; } + + public EntityCreateDbContextAfterEventArgs(object entity,DbContext dbContext) + { + Entity = entity; + DbContext = dbContext; + } + } +} diff --git a/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs b/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs index d02f8703..5fb4e0a7 100644 --- a/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs +++ b/src/ShardingCore/Sharding/ShardingDbContextExecutors/ShardingDbContextExecutor.cs @@ -35,6 +35,13 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors /// public class ShardingDbContextExecutor : IShardingDbContextExecutor { + + + public event EventHandler EntityCreateDbContextBefore; + public event EventHandler EntityCreateDbContextAfter; + public event EventHandler CreateDbContextBefore; + public event EventHandler CreateDbContextAfter; + private readonly ILogger _logger; private readonly DbContext _shardingDbContext; @@ -106,19 +113,29 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors public DbContext CreateDbContext(CreateDbContextStrategyEnum strategy, string dataSourceName, IRouteTail routeTail) { + if (CreateDbContextBefore != null) + { + CreateDbContextBefore.Invoke(this,new CreateDbContextBeforeEventArgs(strategy,dataSourceName,routeTail)); + } + + DbContext dbContext; if (CreateDbContextStrategyEnum.ShareConnection == strategy) { var dataSourceDbContext = GetDataSourceDbContext(dataSourceName); - return dataSourceDbContext.CreateDbContext(routeTail); + dbContext= dataSourceDbContext.CreateDbContext(routeTail); } else { var parallelDbContextOptions = CreateParallelDbContextOptions(dataSourceName, strategy); - var dbContext = + dbContext = _dbContextCreator.CreateDbContext(_shardingDbContext, parallelDbContextOptions, routeTail); dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - return dbContext; } + if (CreateDbContextAfter != null) + { + CreateDbContextAfter.Invoke(this,new CreateDbContextAfterEventArgs(strategy,dataSourceName,routeTail,dbContext)); + } + return dbContext; } private DbContextOptions CreateParallelDbContextOptions(string dataSourceName, @@ -136,12 +153,25 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors public DbContext CreateGenericDbContext(TEntity entity) where TEntity : class { + + if (EntityCreateDbContextBefore != null) + { + EntityCreateDbContextBefore.Invoke(this,new EntityCreateDbContextBeforeEventArgs(entity)); + } + var realEntityType = _trackerManager.TranslateEntityType(entity.GetType()); var dataSourceName = GetDataSourceName(entity,realEntityType); var tail = GetTableTail(dataSourceName, entity,realEntityType); - return CreateDbContext(CreateDbContextStrategyEnum.ShareConnection, dataSourceName, + var dbContext = CreateDbContext(CreateDbContextStrategyEnum.ShareConnection, dataSourceName, _routeTailFactory.Create(tail)); + + if (EntityCreateDbContextAfter != null) + { + EntityCreateDbContextAfter.Invoke(this,new EntityCreateDbContextAfterEventArgs(entity,dbContext)); + } + + return dbContext; } public IVirtualDataSource GetVirtualDataSource() From cd002c8484ee8161a83bf1897e1f77b4e3d27595 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Fri, 23 Dec 2022 12:45:08 +0800 Subject: [PATCH 04/12] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dabpzero=E7=9A=84demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbstractShardingAbpZeroDbContext.cs | 505 ++---------------- 1 file changed, 41 insertions(+), 464 deletions(-) diff --git a/samples/Samples.AbpSharding/AbstractShardingAbpZeroDbContext.cs b/samples/Samples.AbpSharding/AbstractShardingAbpZeroDbContext.cs index ff81b29d..a8175a15 100644 --- a/samples/Samples.AbpSharding/AbstractShardingAbpZeroDbContext.cs +++ b/samples/Samples.AbpSharding/AbstractShardingAbpZeroDbContext.cs @@ -43,465 +43,23 @@ namespace Samples.AbpSharding if (wrapOptionsExtension != null) { _shardingDbContextExecutor = new ShardingDbContextExecutor(this); + _shardingDbContextExecutor.EntityCreateDbContextBefore += (sender, args) => + { + CheckAndSetShardingKeyThatSupportAutoCreate(args.Entity); + }; + _shardingDbContextExecutor.CreateDbContextAfter += (sender, args) => + { + var shardingDbContextExecutor = (IShardingDbContextExecutor)sender; + var argsDbContext = args.DbContext; + var shellDbContext = shardingDbContextExecutor.GetShellDbContext(); + FillDbContextInject(shellDbContext, argsDbContext); + }; } } - /// - /// 是否是真正的执行者 - /// - protected bool isExecutor => _shardingDbContextExecutor == null; - - /// - /// 路由表 - /// public IRouteTail RouteTail { get; set; } - - public override EntityEntry Add(object entity) - { - if (isExecutor) - base.Add(entity); - return CreateGenericDbContext(entity).Add(entity); - } - - public override EntityEntry Add(TEntity entity) - { - if (isExecutor) - return base.Add(entity); - return CreateGenericDbContext(entity).Add(entity); - } - - - public override ValueTask> AddAsync(TEntity entity, CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - return base.AddAsync(entity, cancellationToken); - return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken); - } - - public override ValueTask AddAsync(object entity, CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - return base.AddAsync(entity, cancellationToken); - return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken); - } - - public override void AddRange(params object[] entities) - { - if (isExecutor) - { - base.AddRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.AddRange(group.Select(o => o.Entity)); - } - } - - public override void AddRange(IEnumerable entities) - { - if (isExecutor) - { - base.AddRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.AddRange(group.Select(o => o.Entity)); - } - } - - public override async Task AddRangeAsync(params object[] entities) - { - if (isExecutor) - { - await base.AddRangeAsync(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - await group.Key.AddRangeAsync(group.Select(o => o.Entity)); - } - } - - public override async Task AddRangeAsync(IEnumerable entities, CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - { - await base.AddRangeAsync(entities, cancellationToken); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - await group.Key.AddRangeAsync(group.Select(o => o.Entity)); - } - } - - public override EntityEntry Attach(TEntity entity) - { - if (isExecutor) - return base.Attach(entity); - return CreateGenericDbContext(entity).Attach(entity); - } - - public override EntityEntry Attach(object entity) - { - if (isExecutor) - return base.Attach(entity); - return CreateGenericDbContext(entity).Attach(entity); - } - - public override void AttachRange(params object[] entities) - { - if (isExecutor) - { - base.AttachRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.AttachRange(group.Select(o => o.Entity)); - } - } - - public override void AttachRange(IEnumerable entities) - { - if (isExecutor) - { - base.AttachRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.AttachRange(group.Select(o => o.Entity)); - } - } - - public override EntityEntry Entry(TEntity entity) - { - if (isExecutor) - return base.Entry(entity); - return CreateGenericDbContext(entity).Entry(entity); - } - - public override EntityEntry Entry(object entity) - { - if (isExecutor) - return base.Entry(entity); - return CreateGenericDbContext(entity).Entry(entity); - } - - public override EntityEntry Update(TEntity entity) - { - if (isExecutor) - return base.Update(entity); - return CreateGenericDbContext(entity).Update(entity); - } - - public override EntityEntry Update(object entity) - { - if (isExecutor) - return base.Update(entity); - return CreateGenericDbContext(entity).Update(entity); - } - - public override void UpdateRange(params object[] entities) - { - if (isExecutor) - { - base.UpdateRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.UpdateRange(group.Select(o => o.Entity)); - } - } - - public override void UpdateRange(IEnumerable entities) - { - if (isExecutor) - { - base.UpdateRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.UpdateRange(group.Select(o => o.Entity)); - } - } - - public override EntityEntry Remove(TEntity entity) - { - if (isExecutor) - return base.Remove(entity); - return CreateGenericDbContext(entity).Remove(entity); - } - - public override EntityEntry Remove(object entity) - { - if (isExecutor) - return base.Remove(entity); - return CreateGenericDbContext(entity).Remove(entity); - } - - public override void RemoveRange(params object[] entities) - { - if (isExecutor) - { - base.RemoveRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.RemoveRange(group.Select(o => o.Entity)); - } - } - - public override void RemoveRange(IEnumerable entities) - { - if (isExecutor) - { - base.RemoveRange(entities); - return; - } - var groups = entities.Select(o => - { - var dbContext = CreateGenericDbContext(o); - return new - { - DbContext = dbContext, - Entity = o - }; - }).GroupBy(g => g.DbContext); - - foreach (var group in groups) - { - group.Key.RemoveRange(group.Select(o => o.Entity)); - } - } - - public override int SaveChanges() - { - - if (isExecutor) - return base.SaveChanges(); - return this.SaveChanges(true); - } - - public override int SaveChanges(bool acceptAllChangesOnSuccess) - { - if (isExecutor) - return base.SaveChanges(acceptAllChangesOnSuccess); - //ApplyShardingConcepts(); - int i = 0; - //如果是内部开的事务就内部自己消化 - if (Database.CurrentTransaction == null && _shardingDbContextExecutor.IsMultiDbContext) - { - using (var tran = Database.BeginTransaction()) - { - i = _shardingDbContextExecutor.SaveChanges(acceptAllChangesOnSuccess); - tran.Commit(); - } - } - else - { - i = _shardingDbContextExecutor.SaveChanges(acceptAllChangesOnSuccess); - } - - return i; - } - - - public override Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - return base.SaveChangesAsync(cancellationToken); - return this.SaveChangesAsync(true, cancellationToken); - } - - public override async Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) - { - if (isExecutor) - return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - //ApplyShardingConcepts(); - int i = 0; - //如果是内部开的事务就内部自己消化 - if (Database.CurrentTransaction == null && _shardingDbContextExecutor.IsMultiDbContext) - { - using (var tran = await Database.BeginTransactionAsync(cancellationToken)) - { - i = await _shardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - - await tran.CommitAsync(cancellationToken); - } - } - else - { - i = await _shardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); - } - - - return i; - } - - public override void Dispose() - { - - if (isExecutor) - { - base.Dispose(); - } - else - { - _shardingDbContextExecutor.Dispose(); - base.Dispose(); - } - } - - public override async ValueTask DisposeAsync() - { - if (isExecutor) - { - await base.DisposeAsync(); - } - else - { - await _shardingDbContextExecutor.DisposeAsync(); - - await base.DisposeAsync(); - } - } - - #region Sharding Core 方法实现 - /// - /// 根据查询获取DbContext - /// - /// - /// - /// - /// - public DbContext GetDbContext(string dataSourceName, CreateDbContextStrategyEnum strategy, IRouteTail routeTail) - { - var dbContext = _shardingDbContextExecutor.CreateDbContext( - strategy, - dataSourceName, - routeTail - ); - - this.FillDbContextInject(dbContext); - - return dbContext; - } - - /// - /// 根据对象创建通用的dbcontext - /// - /// - /// - /// - public DbContext CreateGenericDbContext(TEntity entity) where TEntity : class - { - CheckAndSetShardingKeyThatSupportAutoCreate(entity); - - var dbContext = _shardingDbContextExecutor.CreateGenericDbContext(entity); - - this.FillDbContextInject(dbContext); - - return dbContext; - } public IShardingDbContextExecutor GetShardingExecutor() { @@ -559,50 +117,69 @@ namespace Samples.AbpSharding /// /// 填充DbContext需要的依赖项 /// + /// /// - protected virtual void FillDbContextInject(DbContext dbContext) + protected virtual void FillDbContextInject(DbContext shellDbContext,DbContext dbContext) { - if (dbContext is AbpZeroCommonDbContext abpDbContext) + if (shellDbContext is AbpZeroCommonDbContext abpShellDbContext&& dbContext is AbpZeroCommonDbContext abpDbContext) { // AbpZeroCommonDbContext if (abpDbContext.EntityHistoryHelper == null) { - abpDbContext.EntityHistoryHelper = this.EntityHistoryHelper; + abpDbContext.EntityHistoryHelper = abpShellDbContext.EntityHistoryHelper; } // AbpDbContext if (abpDbContext.AbpSession == null) { - abpDbContext.AbpSession = this.AbpSession; + abpDbContext.AbpSession = abpShellDbContext.AbpSession; } if (abpDbContext.EntityChangeEventHelper == null) { - abpDbContext.EntityChangeEventHelper = this.EntityChangeEventHelper; + abpDbContext.EntityChangeEventHelper = abpShellDbContext.EntityChangeEventHelper; } if (abpDbContext.Logger == null) { - abpDbContext.Logger = this.Logger; + abpDbContext.Logger = abpShellDbContext.Logger; } if (abpDbContext.EventBus == null) { - abpDbContext.EventBus = this.EventBus; + abpDbContext.EventBus = abpShellDbContext.EventBus; } if (abpDbContext.GuidGenerator == null) { - abpDbContext.GuidGenerator = this.GuidGenerator; + abpDbContext.GuidGenerator = abpShellDbContext.GuidGenerator; } if (abpDbContext.CurrentUnitOfWorkProvider == null) { - abpDbContext.CurrentUnitOfWorkProvider = this.CurrentUnitOfWorkProvider; + abpDbContext.CurrentUnitOfWorkProvider = abpShellDbContext.CurrentUnitOfWorkProvider; } if (abpDbContext.MultiTenancyConfig == null) { - abpDbContext.MultiTenancyConfig = this.MultiTenancyConfig; + abpDbContext.MultiTenancyConfig = abpShellDbContext.MultiTenancyConfig; } - abpDbContext.SuppressAutoSetTenantId = this.SuppressAutoSetTenantId; + abpDbContext.SuppressAutoSetTenantId = abpShellDbContext.SuppressAutoSetTenantId; } } #endregion + + public override void Dispose() + { + + _shardingDbContextExecutor?.Dispose(); + base.Dispose(); + } + + public override async ValueTask DisposeAsync() + { + if(_shardingDbContextExecutor!=null) + { + await _shardingDbContextExecutor.DisposeAsync(); + } + + await base.DisposeAsync(); + } + } } From 7bc9751e0a8ffe095c28e10f847e282a18d6482c Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Fri, 23 Dec 2022 15:15:55 +0800 Subject: [PATCH 05/12] 7.x.1.1 --- ShardingCore.sln | 2 +- nuget-publish.bat | 10 ++++---- .../EFCores/EFCore2x/ShardingStateManager.cs | 19 +++++--------- .../EFCores/EFCore3x/ShardingStateManager.cs | 19 +++++--------- .../EFCores/EFCore5x/ShardingStateManager.cs | 19 +++++--------- .../EFCores/EFCore6x/ShardingStateManager.cs | 19 +++++--------- .../EFCores/EFCore7x/ShardingStateManager.cs | 20 ++++++--------- .../Exceptions/ShardingCoreException.cs | 5 +++- .../ShardingCoreNotImplementedException.cs | 25 +++++++++++++++++++ src/ShardingCore/ShardingCore.csproj | 2 +- src2/ShardingCore2/ShardingCore2.csproj | 2 +- src3/ShardingCore3/ShardingCore3.csproj | 2 +- src5/ShardingCore5/ShardingCore5.csproj | 2 +- src6/ShardingCore6/ShardingCore6.csproj | 2 +- .../ShardingCore.Test2x.csproj | 4 ++- 15 files changed, 74 insertions(+), 78 deletions(-) create mode 100644 src/ShardingCore/Exceptions/ShardingCoreNotImplementedException.cs diff --git a/ShardingCore.sln b/ShardingCore.sln index 2481fe62..234b24bb 100644 --- a/ShardingCore.sln +++ b/ShardingCore.sln @@ -55,7 +55,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.ShardingConsole", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.OracleIssue", "samples\Sample.OracleIssue\Sample.OracleIssue.csproj", "{BF4FEA2A-3F09-47D8-9BF7-4261D8D1671D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShardingCore.Test6x", "test\ShardingCore.Test6x\ShardingCore.Test6x.csproj", "{8ED3A191-5A29-4599-B383-9FD225CC0BA2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShardingCore.Test6x", "test\ShardingCore.Test6x\ShardingCore.Test6x.csproj", "{8ED3A191-5A29-4599-B383-9FD225CC0BA2}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src6", "src6", "{585A790B-8B19-430F-BEB7-9F7D1A3AAFAA}" EndProject diff --git a/nuget-publish.bat b/nuget-publish.bat index fe6c6e7b..6daa4eaa 100644 --- a/nuget-publish.bat +++ b/nuget-publish.bat @@ -1,10 +1,10 @@ :start ::定义版本 -set EFCORE7=7.7.0.9 -set EFCORE6=7.6.0.9 -set EFCORE5=7.5.0.9 -set EFCORE3=7.3.0.9 -set EFCORE2=7.2.0.9 +set EFCORE7=7.7.1.1-preview1 +set EFCORE6=7.6.1.1-preview1 +set EFCORE5=7.5.1.1-preview1 +set EFCORE3=7.3.1.1-preview1 +set EFCORE2=7.2.1.1-preview1 ::删除所有bin与obj下的文件 @echo off diff --git a/src/ShardingCore/EFCores/EFCore2x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore2x/ShardingStateManager.cs index 41dee844..a72555cb 100644 --- a/src/ShardingCore/EFCores/EFCore2x/ShardingStateManager.cs +++ b/src/ShardingCore/EFCores/EFCore2x/ShardingStateManager.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Exceptions; using ShardingCore.Sharding.Abstractions; namespace ShardingCore.EFCores @@ -35,34 +36,26 @@ namespace ShardingCore.EFCores public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) { var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var findEntityType = genericDbContext.Model.FindEntityType(entity.GetType()); var dbContextDependencies = genericDbContext.GetService(); var stateManager = dbContextDependencies.StateManager; - return stateManager.GetOrCreateEntry(entity,entityType); + return stateManager.GetOrCreateEntry(entity, findEntityType); } public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer, ISet handledForeignKeys) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer, handledForeignKeys); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, entityType); + throw new ShardingCoreNotImplementedException(); } public override int SaveChanges(bool acceptAllChangesOnSuccess) diff --git a/src/ShardingCore/EFCores/EFCore3x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore3x/ShardingStateManager.cs index 7b745e21..72f8c943 100644 --- a/src/ShardingCore/EFCores/EFCore3x/ShardingStateManager.cs +++ b/src/ShardingCore/EFCores/EFCore3x/ShardingStateManager.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Exceptions; using ShardingCore.Sharding.Abstractions; namespace ShardingCore.EFCores @@ -35,33 +36,25 @@ namespace ShardingCore.EFCores public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) { var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var findEntityType = genericDbContext.Model.FindEntityType(entity.GetType()); var dbContextDependencies = genericDbContext.GetService(); var stateManager = dbContextDependencies.StateManager; - return stateManager.GetOrCreateEntry(entity,entityType); + return stateManager.GetOrCreateEntry(entity, findEntityType); } public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, entityType, throwOnTypeMismatch); + throw new ShardingCoreNotImplementedException(); } public override int SaveChanges(bool acceptAllChangesOnSuccess) diff --git a/src/ShardingCore/EFCores/EFCore5x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore5x/ShardingStateManager.cs index c2d13098..287a50bb 100644 --- a/src/ShardingCore/EFCores/EFCore5x/ShardingStateManager.cs +++ b/src/ShardingCore/EFCores/EFCore5x/ShardingStateManager.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Exceptions; using ShardingCore.Sharding.Abstractions; namespace ShardingCore.EFCores @@ -35,33 +36,25 @@ namespace ShardingCore.EFCores public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) { var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var findEntityType = genericDbContext.Model.FindEntityType(entity.GetType()); var dbContextDependencies = genericDbContext.GetService(); var stateManager = dbContextDependencies.StateManager; - return stateManager.GetOrCreateEntry(entity,entityType); + return stateManager.GetOrCreateEntry(entity, findEntityType); } public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, entityType, throwOnTypeMismatch); + throw new ShardingCoreNotImplementedException(); } public override int SaveChanges(bool acceptAllChangesOnSuccess) diff --git a/src/ShardingCore/EFCores/EFCore6x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore6x/ShardingStateManager.cs index 3f3149e3..87e20090 100644 --- a/src/ShardingCore/EFCores/EFCore6x/ShardingStateManager.cs +++ b/src/ShardingCore/EFCores/EFCore6x/ShardingStateManager.cs @@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Exceptions; using ShardingCore.Sharding.Abstractions; namespace ShardingCore.EFCores @@ -35,33 +36,25 @@ namespace ShardingCore.EFCores public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) { var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var findEntityType = genericDbContext.Model.FindEntityType(entity.GetType()); var dbContextDependencies = genericDbContext.GetService(); var stateManager = dbContextDependencies.StateManager; - return stateManager.GetOrCreateEntry(entity,entityType); + return stateManager.GetOrCreateEntry(entity, findEntityType); } public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, entityType, throwOnTypeMismatch); + throw new ShardingCoreNotImplementedException(); } public override int SaveChanges(bool acceptAllChangesOnSuccess) diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs index 154d9a8f..6f968cc3 100644 --- a/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs +++ b/src/ShardingCore/EFCores/EFCore7x/ShardingStateManager.cs @@ -1,5 +1,6 @@ #if EFCORE7 +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -9,6 +10,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage; +using ShardingCore.Exceptions; using ShardingCore.Sharding.Abstractions; namespace ShardingCore.EFCores @@ -33,33 +35,25 @@ namespace ShardingCore.EFCores public override InternalEntityEntry GetOrCreateEntry(object entity, IEntityType entityType) { var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); + var findEntityType = genericDbContext.Model.FindEntityType(entity.GetType()); var dbContextDependencies = genericDbContext.GetService(); var stateManager = dbContextDependencies.StateManager; - return stateManager.GetOrCreateEntry(entity,entityType); + return stateManager.GetOrCreateEntry(entity, findEntityType); } public override InternalEntityEntry StartTrackingFromQuery(IEntityType baseEntityType, object entity, in ValueBuffer valueBuffer) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.StartTrackingFromQuery(baseEntityType, entity, in valueBuffer); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, bool throwOnNonUniqueness = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, throwOnNonUniqueness); + throw new ShardingCoreNotImplementedException(); } public override InternalEntityEntry TryGetEntry(object entity, IEntityType entityType, bool throwOnTypeMismatch = true) { - var genericDbContext = _currentShardingDbContext.GetShardingExecutor().CreateGenericDbContext(entity); - var dbContextDependencies = genericDbContext.GetService(); - var stateManager = dbContextDependencies.StateManager; - return stateManager.TryGetEntry(entity, entityType, throwOnTypeMismatch); + throw new ShardingCoreNotImplementedException(); } public override int SaveChanges(bool acceptAllChangesOnSuccess) diff --git a/src/ShardingCore/Exceptions/ShardingCoreException.cs b/src/ShardingCore/Exceptions/ShardingCoreException.cs index 44a2c4b9..7f67c2c5 100644 --- a/src/ShardingCore/Exceptions/ShardingCoreException.cs +++ b/src/ShardingCore/Exceptions/ShardingCoreException.cs @@ -16,7 +16,10 @@ namespace ShardingCore.Exceptions [ExcludeFromCodeCoverage] public class ShardingCoreException : Exception { - + public ShardingCoreException() + { + + } public ShardingCoreException(string message) : base(message) { } diff --git a/src/ShardingCore/Exceptions/ShardingCoreNotImplementedException.cs b/src/ShardingCore/Exceptions/ShardingCoreNotImplementedException.cs new file mode 100644 index 00000000..0ea43e0d --- /dev/null +++ b/src/ShardingCore/Exceptions/ShardingCoreNotImplementedException.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShardingCore.Exceptions +{ + [ExcludeFromCodeCoverage] + public class ShardingCoreNotImplementedException:ShardingCoreException + { + public ShardingCoreNotImplementedException() + { + + } + public ShardingCoreNotImplementedException(string message) : base(message) + { + } + + public ShardingCoreNotImplementedException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/ShardingCore/ShardingCore.csproj b/src/ShardingCore/ShardingCore.csproj index 967d686a..7841de39 100644 --- a/src/ShardingCore/ShardingCore.csproj +++ b/src/ShardingCore/ShardingCore.csproj @@ -1,7 +1,7 @@  net6.0 - 7.7.0.11 + $(EFCORE7) true TRACE;DEBUG;EFCORE7; latest diff --git a/src2/ShardingCore2/ShardingCore2.csproj b/src2/ShardingCore2/ShardingCore2.csproj index 12b523ac..9991f715 100644 --- a/src2/ShardingCore2/ShardingCore2.csproj +++ b/src2/ShardingCore2/ShardingCore2.csproj @@ -2,7 +2,7 @@ netstandard2.0 - 7.2.0.11 + $(EFCORE2) true TRACE;DEBUG;EFCORE2; 9.0 diff --git a/src3/ShardingCore3/ShardingCore3.csproj b/src3/ShardingCore3/ShardingCore3.csproj index d7d0da04..7bfb0be2 100644 --- a/src3/ShardingCore3/ShardingCore3.csproj +++ b/src3/ShardingCore3/ShardingCore3.csproj @@ -1,7 +1,7 @@  netstandard2.0 - 7.3.0.11 + $(EFCORE3) true TRACE;DEBUG;EFCORE3; 9.0 diff --git a/src5/ShardingCore5/ShardingCore5.csproj b/src5/ShardingCore5/ShardingCore5.csproj index 84209a90..3c222f1a 100644 --- a/src5/ShardingCore5/ShardingCore5.csproj +++ b/src5/ShardingCore5/ShardingCore5.csproj @@ -2,7 +2,7 @@ netstandard2.1 - 7.5.0.11 + $(EFCORE5) true TRACE;DEBUG;EFCORE5; 9.0 diff --git a/src6/ShardingCore6/ShardingCore6.csproj b/src6/ShardingCore6/ShardingCore6.csproj index 5d770f9d..63a12978 100644 --- a/src6/ShardingCore6/ShardingCore6.csproj +++ b/src6/ShardingCore6/ShardingCore6.csproj @@ -2,7 +2,7 @@ net6.0 - 7.6.0.11 + $(EFCORE6) true TRACE;DEBUG;EFCORE6; 9.0 diff --git a/test/ShardingCore.Test2x/ShardingCore.Test2x.csproj b/test/ShardingCore.Test2x/ShardingCore.Test2x.csproj index f64d8834..eda65ee7 100644 --- a/test/ShardingCore.Test2x/ShardingCore.Test2x.csproj +++ b/test/ShardingCore.Test2x/ShardingCore.Test2x.csproj @@ -1,10 +1,12 @@  - netcoreapp2.2 + netcoreapp3.1 9.0 + + From 14b0f747fb0fa4e76755d9d582459ab6e8c37048 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Fri, 23 Dec 2022 16:32:54 +0800 Subject: [PATCH 06/12] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=86=E5=BA=93?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/WeatherForecastController.cs | 11 +++++++++++ samples/Sample.MySql/Startup.cs | 12 ++++++------ ...AbstractShardingOperatorVirtualDataSourceRoute.cs | 2 +- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/samples/Sample.MySql/Controllers/WeatherForecastController.cs b/samples/Sample.MySql/Controllers/WeatherForecastController.cs index 35f412bc..a85b410f 100644 --- a/samples/Sample.MySql/Controllers/WeatherForecastController.cs +++ b/samples/Sample.MySql/Controllers/WeatherForecastController.cs @@ -244,5 +244,16 @@ namespace Sample.MySql.Controllers // var sysUserMods2 = await _defaultTableDbContext.Set().FromSqlRaw("select * from SysTest where id='2'").ToListAsync(); return Ok(); } + [HttpGet] + public async Task Get6() + { + var sysUserMod = await _defaultTableDbContext.Set().FirstOrDefaultAsync(); + sysUserMod.Age = new Random().Next(1,999); + _defaultTableDbContext.Update(sysUserMod); + _defaultTableDbContext.SaveChanges(); + // 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(); + } } } diff --git a/samples/Sample.MySql/Startup.cs b/samples/Sample.MySql/Startup.cs index 09fea956..bf23ffe8 100644 --- a/samples/Sample.MySql/Startup.cs +++ b/samples/Sample.MySql/Startup.cs @@ -104,17 +104,17 @@ namespace Sample.MySql o.UseShardingQuery((conStr, builder) => { - builder.UseMySql(conStr, new MySqlServerVersion(new Version())); - // .UseLoggerFactory(efLogger) - // .EnableSensitiveDataLogging() + builder.UseMySql(conStr, new MySqlServerVersion(new Version())) + .UseLoggerFactory(efLogger) + .EnableSensitiveDataLogging(); //.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); }); o.UseShardingTransaction((connection, builder) => { builder - .UseMySql(connection, new MySqlServerVersion(new Version())); - // .UseLoggerFactory(efLogger) - // .EnableSensitiveDataLogging() + .UseMySql(connection, new MySqlServerVersion(new Version())) + .UseLoggerFactory(efLogger) + .EnableSensitiveDataLogging(); //.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); }); o.AddDefaultDataSource("ds0", diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingOperatorVirtualDataSourceRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingOperatorVirtualDataSourceRoute.cs index e4e3366f..d19bf616 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingOperatorVirtualDataSourceRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingOperatorVirtualDataSourceRoute.cs @@ -71,7 +71,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions var dataSources = allDataSourceNames.Where(o => o== shardingKeyToDataSource).ToList(); if (dataSources.IsEmpty()) { - throw new ShardingCoreException($"sharding key route not match {EntityMetadata.EntityType} -> [{EntityMetadata.ShardingTableProperty.Name}] ->【{shardingKey}】 all data sources ->[{string.Join(",", allDataSourceNames.Select(o=>o))}]"); + throw new ShardingCoreException($"sharding key route not match {EntityMetadata.EntityType} -> [{EntityMetadata.ShardingDataSourceProperty.Name}] ->【{shardingKey}】 all data sources ->[{string.Join(",", allDataSourceNames.Select(o=>o))}]"); } if (dataSources.Count > 1) From fd548bd25871b2e0d39026ac77f3860784f187c2 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Tue, 3 Jan 2023 17:16:45 +0800 Subject: [PATCH 07/12] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=A8=E6=9E=84?= =?UTF-8?q?=E9=80=A0=E5=87=BD=E6=95=B0=E7=9A=84group=20by=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/WeatherForecastController.cs | 11 ++++ .../DbContexts/DefaultShardingDbContext.cs | 2 +- samples/Sample.MySql/Startup.cs | 2 +- .../AbstractShardingAbpDbContext.cs | 48 +++++++-------- .../AbstractShardingAbpZeroDbContext.cs | 58 +++++++++---------- .../EFCore7x/ShardingOptionsExtension.cs | 3 + .../Extensions/ShardingDbContextExtension.cs | 13 +++++ .../Sharding/AbstractShardingDbContext.cs | 28 ++++----- .../AggregateExtensions/AggregateExtension.cs | 2 +- src/ShardingCore/ShardingCoreExtension.cs | 30 +++++----- 10 files changed, 113 insertions(+), 84 deletions(-) diff --git a/samples/Sample.MySql/Controllers/WeatherForecastController.cs b/samples/Sample.MySql/Controllers/WeatherForecastController.cs index a85b410f..117a3ba3 100644 --- a/samples/Sample.MySql/Controllers/WeatherForecastController.cs +++ b/samples/Sample.MySql/Controllers/WeatherForecastController.cs @@ -255,5 +255,16 @@ namespace Sample.MySql.Controllers // var sysUserMods2 = await _defaultTableDbContext.Set().FromSqlRaw("select * from SysTest where id='2'").ToListAsync(); return Ok(); } + [HttpGet] + public async Task Get7() + { + var sysUserMod = await _defaultTableDbContext.Set().FindAsync("101"); + sysUserMod.Age = new Random().Next(1,999); + _defaultTableDbContext.Update(sysUserMod); + _defaultTableDbContext.SaveChanges(); + // 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(); + } } } diff --git a/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs b/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs index 35057f79..1912278c 100644 --- a/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs +++ b/samples/Sample.MySql/DbContexts/DefaultShardingDbContext.cs @@ -43,7 +43,7 @@ namespace Sample.MySql.DbContexts // modelBuilder.Entity().HasData(new SysUserLogByMonth() { Id = "1", Time = DateTime.Now }); // modelBuilder.Entity().HasData(new SysTest() { Id = "1", UserId = "123" }); // modelBuilder.Entity().ToTable(nameof(TestMod)); - // modelBuilder.Entity().ToTable(nameof(TestModItem)); + // modelBuilder.Entity().ToTable("xxx"); } diff --git a/samples/Sample.MySql/Startup.cs b/samples/Sample.MySql/Startup.cs index bf23ffe8..152af3fd 100644 --- a/samples/Sample.MySql/Startup.cs +++ b/samples/Sample.MySql/Startup.cs @@ -105,7 +105,7 @@ namespace Sample.MySql o.UseShardingQuery((conStr, builder) => { builder.UseMySql(conStr, new MySqlServerVersion(new Version())) - .UseLoggerFactory(efLogger) + .UseLoggerFactory(efLogger) .EnableSensitiveDataLogging(); //.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); }); diff --git a/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs b/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs index 89eb4735..54726407 100644 --- a/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs +++ b/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs @@ -26,36 +26,36 @@ namespace Samples.AbpSharding public abstract class AbstractShardingAbpDbContext : AbpDbContext, IShardingDbContext where TDbContext : DbContext { - private readonly IShardingDbContextExecutor _shardingDbContextExecutor; protected AbstractShardingAbpDbContext(DbContextOptions options) : base(options) { - - var wrapOptionsExtension = options.FindExtension(); - if (wrapOptionsExtension != null) - { - _shardingDbContextExecutor = new ShardingDbContextExecutor(this); - _shardingDbContextExecutor.EntityCreateDbContextBefore += (sender, args) => - { - CheckAndSetShardingKeyThatSupportAutoCreate(args.Entity); - }; - _shardingDbContextExecutor.CreateDbContextAfter += (sender, args) => - { - var shardingDbContextExecutor = (IShardingDbContextExecutor)sender; - var argsDbContext = args.DbContext; - var shellDbContext = shardingDbContextExecutor.GetShellDbContext(); - - if (argsDbContext is AbpDbContext abpDbContext&&shellDbContext is AbpDbContext abpShellDbContext && - abpDbContext.LazyServiceProvider == null) - { - abpDbContext.LazyServiceProvider = abpShellDbContext.LazyServiceProvider; - } - }; - } } + + private IShardingDbContextExecutor _shardingDbContextExecutor; public IShardingDbContextExecutor GetShardingExecutor() { - return _shardingDbContextExecutor; + return _shardingDbContextExecutor??=DoCreateShardingDbContextExecutor(); + } + + private IShardingDbContextExecutor DoCreateShardingDbContextExecutor() + { + var shardingDbContextExecutor = this.CreateShardingDbContextExecutor()!; + + shardingDbContextExecutor.EntityCreateDbContextBefore += (sender, args) => + { + CheckAndSetShardingKeyThatSupportAutoCreate(args.Entity); + }; + shardingDbContextExecutor.CreateDbContextAfter += (sender, args) => + { + var argsDbContext = args.DbContext; + + if (argsDbContext is AbpDbContext abpDbContext&& + abpDbContext.LazyServiceProvider == null) + { + abpDbContext.LazyServiceProvider = this.LazyServiceProvider; + } + }; + return shardingDbContextExecutor; } diff --git a/samples/Samples.AbpSharding/AbstractShardingAbpZeroDbContext.cs b/samples/Samples.AbpSharding/AbstractShardingAbpZeroDbContext.cs index a8175a15..cb648d8f 100644 --- a/samples/Samples.AbpSharding/AbstractShardingAbpZeroDbContext.cs +++ b/samples/Samples.AbpSharding/AbstractShardingAbpZeroDbContext.cs @@ -34,36 +34,35 @@ namespace Samples.AbpSharding where TUser : AbpUser where TSelf : AbpZeroDbContext { - private readonly IShardingDbContextExecutor _shardingDbContextExecutor; protected AbstractShardingAbpZeroDbContext(DbContextOptions options) : base(options) { - var wrapOptionsExtension = options.FindExtension(); - if (wrapOptionsExtension != null) - { - _shardingDbContextExecutor = new ShardingDbContextExecutor(this); - _shardingDbContextExecutor.EntityCreateDbContextBefore += (sender, args) => - { - CheckAndSetShardingKeyThatSupportAutoCreate(args.Entity); - }; - _shardingDbContextExecutor.CreateDbContextAfter += (sender, args) => - { - var shardingDbContextExecutor = (IShardingDbContextExecutor)sender; - var argsDbContext = args.DbContext; - var shellDbContext = shardingDbContextExecutor.GetShellDbContext(); - FillDbContextInject(shellDbContext, argsDbContext); - }; - } } public IRouteTail RouteTail { get; set; } #region Sharding Core 方法实现 + private IShardingDbContextExecutor _shardingDbContextExecutor; public IShardingDbContextExecutor GetShardingExecutor() { - return _shardingDbContextExecutor; + return _shardingDbContextExecutor??=DoCreateShardingDbContextExecutor(); + } + private IShardingDbContextExecutor DoCreateShardingDbContextExecutor() + { + var shardingDbContextExecutor = this.CreateShardingDbContextExecutor()!; + + shardingDbContextExecutor.EntityCreateDbContextBefore += (sender, args) => + { + CheckAndSetShardingKeyThatSupportAutoCreate(args.Entity); + }; + shardingDbContextExecutor.CreateDbContextAfter += (sender, args) => + { + var argsDbContext = args.DbContext; + FillDbContextInject(argsDbContext); + }; + return shardingDbContextExecutor; } #endregion @@ -117,48 +116,47 @@ namespace Samples.AbpSharding /// /// 填充DbContext需要的依赖项 /// - /// /// - protected virtual void FillDbContextInject(DbContext shellDbContext,DbContext dbContext) + protected virtual void FillDbContextInject(DbContext dbContext) { - if (shellDbContext is AbpZeroCommonDbContext abpShellDbContext&& dbContext is AbpZeroCommonDbContext abpDbContext) + if ( dbContext is AbpZeroCommonDbContext abpDbContext) { // AbpZeroCommonDbContext if (abpDbContext.EntityHistoryHelper == null) { - abpDbContext.EntityHistoryHelper = abpShellDbContext.EntityHistoryHelper; + abpDbContext.EntityHistoryHelper = this.EntityHistoryHelper; } // AbpDbContext if (abpDbContext.AbpSession == null) { - abpDbContext.AbpSession = abpShellDbContext.AbpSession; + abpDbContext.AbpSession = this.AbpSession; } if (abpDbContext.EntityChangeEventHelper == null) { - abpDbContext.EntityChangeEventHelper = abpShellDbContext.EntityChangeEventHelper; + abpDbContext.EntityChangeEventHelper = this.EntityChangeEventHelper; } if (abpDbContext.Logger == null) { - abpDbContext.Logger = abpShellDbContext.Logger; + abpDbContext.Logger = this.Logger; } if (abpDbContext.EventBus == null) { - abpDbContext.EventBus = abpShellDbContext.EventBus; + abpDbContext.EventBus = this.EventBus; } if (abpDbContext.GuidGenerator == null) { - abpDbContext.GuidGenerator = abpShellDbContext.GuidGenerator; + abpDbContext.GuidGenerator = this.GuidGenerator; } if (abpDbContext.CurrentUnitOfWorkProvider == null) { - abpDbContext.CurrentUnitOfWorkProvider = abpShellDbContext.CurrentUnitOfWorkProvider; + abpDbContext.CurrentUnitOfWorkProvider = this.CurrentUnitOfWorkProvider; } if (abpDbContext.MultiTenancyConfig == null) { - abpDbContext.MultiTenancyConfig = abpShellDbContext.MultiTenancyConfig; + abpDbContext.MultiTenancyConfig = this.MultiTenancyConfig; } - abpDbContext.SuppressAutoSetTenantId = abpShellDbContext.SuppressAutoSetTenantId; + abpDbContext.SuppressAutoSetTenantId = this.SuppressAutoSetTenantId; } } diff --git a/src/ShardingCore/EFCores/EFCore7x/ShardingOptionsExtension.cs b/src/ShardingCore/EFCores/EFCore7x/ShardingOptionsExtension.cs index c3f60cdb..f14abae5 100644 --- a/src/ShardingCore/EFCores/EFCore7x/ShardingOptionsExtension.cs +++ b/src/ShardingCore/EFCores/EFCore7x/ShardingOptionsExtension.cs @@ -2,9 +2,12 @@ using System; using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; using ShardingCore.Core.RuntimeContexts; +using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ShardingDbContextExecutors; namespace ShardingCore.EFCores { diff --git a/src/ShardingCore/Extensions/ShardingDbContextExtension.cs b/src/ShardingCore/Extensions/ShardingDbContextExtension.cs index 19471a8c..8ad33c70 100644 --- a/src/ShardingCore/Extensions/ShardingDbContextExtension.cs +++ b/src/ShardingCore/Extensions/ShardingDbContextExtension.cs @@ -14,11 +14,24 @@ using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.EFCores; using ShardingCore.Sharding; using ShardingCore.Sharding.Abstractions; +using ShardingCore.Sharding.ShardingDbContextExecutors; namespace ShardingCore.Extensions { public static class ShardingDbContextExtension { + public static IShardingDbContextExecutor? CreateShardingDbContextExecutor( + this TDbContext shellDbContext) + where TDbContext:DbContext,IShardingDbContext + { + var shardingWrapOptionsExtension = shellDbContext.GetService().FindExtension(); + if (shardingWrapOptionsExtension != null) + { + return new ShardingDbContextExecutor(shellDbContext); + } + + return default; + } public static bool IsUseReadWriteSeparation(this IShardingDbContext shardingDbContext) { return shardingDbContext.GetShardingExecutor().GetVirtualDataSource().UseReadWriteSeparation; diff --git a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs index f4dfd923..45b8aba5 100644 --- a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs +++ b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs @@ -7,7 +7,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Infrastructure; using ShardingCore.EFCores; +using ShardingCore.Extensions; namespace ShardingCore.Sharding { @@ -23,35 +25,33 @@ namespace ShardingCore.Sharding /// public abstract class AbstractShardingDbContext : DbContext, IShardingDbContext { - protected IShardingDbContextExecutor ShardingDbContextExecutor { get; } - - - public AbstractShardingDbContext(DbContextOptions options) : base(options) + /// + /// 构造函数 + /// + /// + protected AbstractShardingDbContext(DbContextOptions options) : base(options) { - var wrapOptionsExtension = options.FindExtension(); - if (wrapOptionsExtension != null) - { - ShardingDbContextExecutor = new ShardingDbContextExecutor(this); - } + } - + + private IShardingDbContextExecutor _shardingDbContextExecutor; public IShardingDbContextExecutor GetShardingExecutor() { - return ShardingDbContextExecutor; + return _shardingDbContextExecutor??=this.CreateShardingDbContextExecutor(); } public override void Dispose() { - ShardingDbContextExecutor?.Dispose(); + _shardingDbContextExecutor?.Dispose(); base.Dispose(); } #if !EFCORE2 public override async ValueTask DisposeAsync() { - if (ShardingDbContextExecutor!=null) + if (_shardingDbContextExecutor!=null) { - await ShardingDbContextExecutor.DisposeAsync(); + await _shardingDbContextExecutor.DisposeAsync(); } await base.DisposeAsync(); diff --git a/src/ShardingCore/Sharding/Enumerators/AggregateExtensions/AggregateExtension.cs b/src/ShardingCore/Sharding/Enumerators/AggregateExtensions/AggregateExtension.cs index 60ce8def..60dc9b9c 100644 --- a/src/ShardingCore/Sharding/Enumerators/AggregateExtensions/AggregateExtension.cs +++ b/src/ShardingCore/Sharding/Enumerators/AggregateExtensions/AggregateExtension.cs @@ -37,10 +37,10 @@ namespace ShardingCore.Sharding.Enumerators.AggregateExtensions } else { - var parameters = allProperties.Select(o => o.GetValue(source)).ToArray(); if (anonType.GetConstructors().Length == 1 && anonType.GetConstructors()[0].GetParameters().Length == allPropertyTypes.Length) { + var parameters = allProperties.Select(o => o.GetValue(source)).ToArray(); return (TSource)Activator.CreateInstance(anonType, parameters); } else diff --git a/src/ShardingCore/ShardingCoreExtension.cs b/src/ShardingCore/ShardingCoreExtension.cs index 31277bb8..17b9971a 100644 --- a/src/ShardingCore/ShardingCoreExtension.cs +++ b/src/ShardingCore/ShardingCoreExtension.cs @@ -123,12 +123,11 @@ namespace ShardingCore shardingConfigOptions.ShardingMigrationConfigure?.Invoke(dbContextOptionsBuilder); var virtualDataSource = shardingRuntimeContext.GetVirtualDataSource(); var connectionString = virtualDataSource.GetConnectionString(virtualDataSource.DefaultDataSourceName); - var contextOptionsBuilder = virtualDataSource.ConfigurationParams + virtualDataSource.ConfigurationParams .UseDbContextOptionsBuilder(connectionString, dbContextOptionsBuilder) - .UseShardingMigrator() .UseSharding(shardingRuntimeContext); - virtualDataSource.ConfigurationParams.UseShellDbContextOptionBuilder(contextOptionsBuilder); + virtualDataSource.ConfigurationParams.UseShellDbContextOptionBuilder(dbContextOptionsBuilder); return dbContextOptionsBuilder; } @@ -210,20 +209,27 @@ namespace ShardingCore return services; } +#pragma warning disable EF1001 + /// + /// + /// + /// + /// + /// public static DbContextOptionsBuilder UseSharding( this DbContextOptionsBuilder optionsBuilder, IShardingRuntimeContext shardingRuntimeContext) { - return optionsBuilder.UseShardingWrapMark().UseShardingOptions(shardingRuntimeContext) - // .ReplaceService() + return optionsBuilder + .UseShardingWrapMark() + .UseShardingMigrator() + .UseShardingOptions(shardingRuntimeContext) .ReplaceService() .ReplaceService() - .ReplaceService() - .ReplaceService() - .ReplaceService(); + .ReplaceService() + .ReplaceService() + .ReplaceService(); } +#pragma warning restore EF1001 public static DbContextOptionsBuilder UseShardingMigrator( this DbContextOptionsBuilder optionsBuilder) @@ -248,12 +254,10 @@ namespace ShardingCore ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(shardingWrapExtension); return optionsBuilder; } - private static ShardingWrapOptionsExtension CreateOrGetShardingWrapExtension( this DbContextOptionsBuilder optionsBuilder) => optionsBuilder.Options.FindExtension() ?? new ShardingWrapOptionsExtension(); - private static ShardingOptionsExtension CreateOrGetShardingOptionsExtension( this DbContextOptionsBuilder optionsBuilder, IShardingRuntimeContext shardingRuntimeContext) => optionsBuilder.Options.FindExtension() ?? From f5018b661600247652e0c83709e965aff95d5fe2 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Wed, 4 Jan 2023 14:51:09 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8C=89=E5=B9=B4?= =?UTF-8?q?=E5=88=86=E8=A1=A8=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- samples/Sample.BulkConsole/Program.cs | 1 + .../AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs | 3 ++- .../AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/samples/Sample.BulkConsole/Program.cs b/samples/Sample.BulkConsole/Program.cs index b1c000e2..6047b097 100644 --- a/samples/Sample.BulkConsole/Program.cs +++ b/samples/Sample.BulkConsole/Program.cs @@ -25,6 +25,7 @@ namespace Sample.BulkConsole }); static void Main(string[] args) { + var s = Guid.NewGuid().ToString("n"); var services = new ServiceCollection(); services.AddLogging(); diff --git a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs index 0a8cf525..cef83a47 100644 --- a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs @@ -22,7 +22,8 @@ namespace ShardingCore.VirtualRoutes.Years var tails=new List(); //提前创建表 - var nowTimeStamp = DateTime.Now.Date; + var now = DateTime.Now; + var nowTimeStamp = new DateTime(now.Year,1,1); if (beginTime > nowTimeStamp) throw new ArgumentException("begin time error"); var currentTimeStamp = beginTime; diff --git a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs index a37b4a4f..22113399 100644 --- a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs @@ -31,7 +31,8 @@ namespace ShardingCore.VirtualRoutes.Years var tails=new List(); //提前创建表 - var nowTimeStamp = DateTime.Now.Date; + var now = DateTime.Now; + var nowTimeStamp = new DateTime(now.Year,1,1); if (beginTime > nowTimeStamp) throw new ArgumentException("begin time error"); var currentTimeStamp = beginTime; From a402ccd6743ec429c3ee3f78309cc730267fe697 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Wed, 4 Jan 2023 15:00:17 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8C=89=E5=B9=B4?= =?UTF-8?q?=E5=88=86=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs | 2 +- .../Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs index cef83a47..637ee45f 100644 --- a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs @@ -18,7 +18,7 @@ namespace ShardingCore.VirtualRoutes.Years public abstract DateTime GetBeginTime(); protected override List CalcTailsOnStart() { - var beginTime = GetBeginTime().Date; + var beginTime = new DateTime(GetBeginTime().Year,1,1); var tails=new List(); //提前创建表 diff --git a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs index 22113399..7aab51a5 100644 --- a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs @@ -27,7 +27,7 @@ namespace ShardingCore.VirtualRoutes.Years /// protected override List CalcTailsOnStart() { - var beginTime = GetBeginTime().Date; + var beginTime = new DateTime(GetBeginTime().Year,1,1); var tails=new List(); //提前创建表 From 8a3ff2721df4f85a53aff2b7075f912497e63ca9 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Wed, 11 Jan 2023 16:43:23 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=BD=93=E5=89=8Ddbcon?= =?UTF-8?q?text=E6=98=AF=E5=90=A6=E6=98=AF=E6=89=A7=E8=A1=8C=E7=9A=84dbcon?= =?UTF-8?q?text=E7=9A=84=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/WeatherForecastController.cs | 2 ++ .../Controllers/WeatherForecastController.cs | 15 +++++++-------- .../Extensions/ShardingDbContextExtension.cs | 2 +- .../Sharding/AbstractShardingDbContext.cs | 15 +++++++++++++-- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/samples/Sample.AutoCreateIfPresent/Controllers/WeatherForecastController.cs b/samples/Sample.AutoCreateIfPresent/Controllers/WeatherForecastController.cs index ddb9a893..314397be 100644 --- a/samples/Sample.AutoCreateIfPresent/Controllers/WeatherForecastController.cs +++ b/samples/Sample.AutoCreateIfPresent/Controllers/WeatherForecastController.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using ShardingCore.Extensions; +using ShardingCore.Extensions.ShardingQueryableExtensions; namespace Sample.AutoCreateIfPresent.Controllers; diff --git a/samples/Sample.MySql/Controllers/WeatherForecastController.cs b/samples/Sample.MySql/Controllers/WeatherForecastController.cs index 117a3ba3..e656a44d 100644 --- a/samples/Sample.MySql/Controllers/WeatherForecastController.cs +++ b/samples/Sample.MySql/Controllers/WeatherForecastController.cs @@ -61,14 +61,13 @@ namespace Sample.MySql.Controllers public IQueryable GetAll() { - var shardingRouteManager = _shardingRuntimeContext.GetShardingRouteManager(); - // var shardingTableCreator = _shardingRuntimeContext.GetShardingTableCreator(); - // var tableRouteManager = _shardingRuntimeContext.GetTableRouteManager(); - // //系统的时间分片都会实现 ITailAppendable 如果不是系统的自定义的转成你自己的对象即可 - // var virtualTableRoute = (ITailAppendable)tableRouteManager.GetRoute(typeof(SysUserMod)); - // //一定要先在路由里面添加尾巴 - // virtualTableRoute.Append("20220921"); - // shardingTableCreator.CreateTable("ds0","20220921"); + var shardingTableCreator = _shardingRuntimeContext.GetShardingTableCreator(); + var tableRouteManager = _shardingRuntimeContext.GetTableRouteManager(); + //系统的时间分片都会实现 ITailAppendable 如果不是系统的自定义的转成你自己的对象即可 + var virtualTableRoute = (ITailAppendable)tableRouteManager.GetRoute(typeof(SysUserMod)); + //一定要先在路由里面添加尾巴 + virtualTableRoute.Append("20220921"); + shardingTableCreator.CreateTable("ds0","20220921"); return _defaultTableDbContext.Set(); } [HttpGet] diff --git a/src/ShardingCore/Extensions/ShardingDbContextExtension.cs b/src/ShardingCore/Extensions/ShardingDbContextExtension.cs index 8ad33c70..482d4b0e 100644 --- a/src/ShardingCore/Extensions/ShardingDbContextExtension.cs +++ b/src/ShardingCore/Extensions/ShardingDbContextExtension.cs @@ -20,7 +20,7 @@ namespace ShardingCore.Extensions { public static class ShardingDbContextExtension { - public static IShardingDbContextExecutor? CreateShardingDbContextExecutor( + public static IShardingDbContextExecutor CreateShardingDbContextExecutor( this TDbContext shellDbContext) where TDbContext:DbContext,IShardingDbContext { diff --git a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs index 45b8aba5..5a3f6b4c 100644 --- a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs +++ b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs @@ -25,6 +25,7 @@ namespace ShardingCore.Sharding /// public abstract class AbstractShardingDbContext : DbContext, IShardingDbContext { + private bool _createExecutor = false; /// /// 构造函数 /// @@ -34,12 +35,22 @@ namespace ShardingCore.Sharding } - private IShardingDbContextExecutor _shardingDbContextExecutor; + private IShardingDbContextExecutor? _shardingDbContextExecutor; public IShardingDbContextExecutor GetShardingExecutor() { - return _shardingDbContextExecutor??=this.CreateShardingDbContextExecutor(); + if (!_createExecutor) + { + _shardingDbContextExecutor=this.CreateShardingDbContextExecutor(); + _createExecutor = true; + } + return _shardingDbContextExecutor; } + /// + /// 当前dbcontext是否是执行的dbcontext + /// + public bool IsExecutor => GetShardingExecutor() == default; + public override void Dispose() { _shardingDbContextExecutor?.Dispose(); From 4f221d080325c0e002382815f912379daf0de7a9 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Thu, 12 Jan 2023 11:43:34 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E4=B8=8D=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E7=9A=84using?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbstractShardingAbpDbContext.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs b/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs index 54726407..10ee3455 100644 --- a/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs +++ b/samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs @@ -1,24 +1,12 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.ChangeTracking; -using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Extensions; using ShardingCore.Sharding.Abstractions; -using ShardingCore.Sharding.ShardingDbContextExecutors; using System; -using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; -using System.Threading; using System.Threading.Tasks; -using ShardingCore.EFCores; -using ShardingCore.Helpers; -using ShardingCore.Utils; using Volo.Abp.Domain.Entities; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Reflection; -using ShardingCore.Core.VirtualDatabase.VirtualDataSources; -using ShardingCore.Exceptions; -using ShardingCore.Sharding; namespace Samples.AbpSharding { From 94451745bdc391fa304a9364a699f21b73e67ae1 Mon Sep 17 00:00:00 2001 From: xuejiaming <326308290@qq.com> Date: Tue, 7 Feb 2023 22:40:54 +0800 Subject: [PATCH 12/12] 1 --- samples/Sample.MySql/Controllers/WeatherForecastController.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/samples/Sample.MySql/Controllers/WeatherForecastController.cs b/samples/Sample.MySql/Controllers/WeatherForecastController.cs index e656a44d..9bea3ff2 100644 --- a/samples/Sample.MySql/Controllers/WeatherForecastController.cs +++ b/samples/Sample.MySql/Controllers/WeatherForecastController.cs @@ -9,6 +9,7 @@ using ShardingCore.Core.RuntimeContexts; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; +using ShardingCore.Extensions.ShardingPageExtensions; using ShardingCore.Extensions.ShardingQueryableExtensions; using ShardingCore.Helpers; @@ -73,6 +74,8 @@ namespace Sample.MySql.Controllers [HttpGet] public async Task Get() { + var s = Guid.NewGuid().ToString(); + var page =await _defaultTableDbContext.Set().Where(o=>o.Id==s).OrderByDescending(o=>o.Time).ToShardingPageAsync(1,2); // var virtualDataSource = _shardingRuntimeContext.GetVirtualDataSource(); // virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource("2023", "xxxxxxxx", false)); // var dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager();