diff --git a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs
index de95b2e5..940de0e7 100644
--- a/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs
+++ b/src/ShardingCore/DbContexts/ShardingDbContextFactory.cs
@@ -34,35 +34,25 @@ namespace ShardingCore.DbContexts
}
public DbContext Create(ShardingDbContextOptions shardingDbContextOptions)
{
+ var tail=shardingDbContextOptions.Tail;
var shardingConfigEntry = _shardingCoreOptions.GetShardingConfig();
- using (var scope = _shardingTableScopeFactory.CreateScope())
+ var dbContext = shardingConfigEntry.Creator(shardingDbContextOptions);
+ if (!string.IsNullOrWhiteSpace(tail) && dbContext is IShardingTableDbContext shardingTableDbContext)
{
- string tail = null;
- string modelChangeKey = null;
- if (!string.IsNullOrWhiteSpace(shardingDbContextOptions.Tail))
- {
- tail = shardingDbContextOptions.Tail;
- modelChangeKey = $"sharding_{tail}";
- }
- scope.ShardingTableAccessor.Context = ShardingTableContext.Create(tail);
- var dbContext= shardingConfigEntry.Creator(shardingDbContextOptions);
- if (modelChangeKey != null&& dbContext is IShardingTableDbContext shardingTableDbContext)
- {
- shardingTableDbContext.ModelChangeKey = modelChangeKey;
- }
-
- var filters = _dbContextCreateFilterManager.GetFilters();
- if (filters.Any())
- {
- foreach (var dbContextCreateFilter in filters)
- {
- dbContextCreateFilter.CreateAfter(dbContext);
- }
- }
- var dbContextModel = dbContext.Model;
- return dbContext;
+ shardingTableDbContext.SetShardingTableDbContextTail(tail);
}
+
+ var filters = _dbContextCreateFilterManager.GetFilters();
+ if (filters.Any())
+ {
+ foreach (var dbContextCreateFilter in filters)
+ {
+ dbContextCreateFilter.CreateAfter(dbContext);
+ }
+ }
+ var dbContextModel = dbContext.Model;
+ return dbContext;
}
public DbContext Create(DbConnection dbConnection,string tail)
diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/IShardingTableAccessor.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/IShardingTableAccessor.cs
deleted file mode 100644
index d287b622..00000000
--- a/src/ShardingCore/DbContexts/ShardingDbContexts/IShardingTableAccessor.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace ShardingCore.DbContexts.ShardingDbContexts
-{
- /*
- * @Author: xjm
- * @Description:
- * @Date: 2021/03/09 00:00:00
- * @Ver: 1.0
- * @Email: 326308290@qq.com
- */
- ///
- ///
- ///
- public interface IShardingTableAccessor
- {
- ShardingTableContext Context { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/IShardingTableScopeFactory.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/IShardingTableScopeFactory.cs
deleted file mode 100644
index 51f6edae..00000000
--- a/src/ShardingCore/DbContexts/ShardingDbContexts/IShardingTableScopeFactory.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace ShardingCore.DbContexts.ShardingDbContexts
-{
- /*
- * @Author: xjm
- * @Description:
- * @Date: 2021/03/09 00:00:00
- * @Ver: 1.0
- * @Email: 326308290@qq.com
- */
- ///
- ///
- ///
- public interface IShardingTableScopeFactory
- {
- ///
- /// 创建查询scope
- ///
- ///
- ShardingTableScope CreateScope();
- }
-}
\ No newline at end of file
diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableAccessor.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableAccessor.cs
deleted file mode 100644
index 72919a47..00000000
--- a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableAccessor.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Threading;
-using ShardingCore.Core.VirtualTables;
-
-namespace ShardingCore.DbContexts.ShardingDbContexts
-{
- /*
- * @Author: xjm
- * @Description:
- * @Date: 2021/03/09 13:08:15
- * @Ver: 1.0
- * @Email: 326308290@qq.com
- */
-
- ///
- ///
- ///
- public class ShardingTableAccessor:IShardingTableAccessor
- {
- private static AsyncLocal _context = new AsyncLocal();
-
- ///
- public ShardingTableContext Context
- {
- get => _context.Value;
- set => _context.Value = value;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableContext.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableContext.cs
deleted file mode 100644
index f1f42fa5..00000000
--- a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableContext.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-namespace ShardingCore.DbContexts.ShardingDbContexts
-{
- /*
- * @Author: xjm
- * @Description:
- * @Date: 2021/03/09 13:04:52
- * @Ver: 1.0
- * @Email: 326308290@qq.com
- */
-
- ///
- /// 分表上下文
- ///
- public class ShardingTableContext
- {
- private ShardingTableContext(string tail)
- {
- Tail = tail;
- }
- public static ShardingTableContext Create(string tail)
- {
- return new ShardingTableContext(tail);
- }
- ///
- /// 尾巴
- ///
- public string Tail { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableScope.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableScope.cs
deleted file mode 100644
index cf04fa67..00000000
--- a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableScope.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System;
-
-namespace ShardingCore.DbContexts.ShardingDbContexts
-{
- /*
- * @Author: xjm
- * @Description:
- * @Date: 2021/03/09 00:00:00
- * @Ver: 1.0
- * @Email: 326308290@qq.com
- */
- ///
- ///
- ///
- public class ShardingTableScope: IDisposable
- {
-
- ///
- /// 分表配置访问器
- ///
- public IShardingTableAccessor ShardingTableAccessor { get; }
-
- ///
- /// 构造函数
- ///
- ///
- public ShardingTableScope(IShardingTableAccessor shardingAccessor)
- {
- ShardingTableAccessor = shardingAccessor;
- }
-
- ///
- /// 回收
- ///
- public void Dispose()
- {
- ShardingTableAccessor.Context = null;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableScopeFactory.cs b/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableScopeFactory.cs
deleted file mode 100644
index 0e61c0a2..00000000
--- a/src/ShardingCore/DbContexts/ShardingDbContexts/ShardingTableScopeFactory.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-namespace ShardingCore.DbContexts.ShardingDbContexts
-{
- /*
- * @Author: xjm
- * @Description:
- * @Date: 2021/03/09 13:13:58
- * @Ver: 1.0
- * @Email: 326308290@qq.com
- */
-
- ///
- ///
- ///
- public class ShardingTableScopeFactory:IShardingTableScopeFactory
- {
- private readonly IShardingTableAccessor _shardingTableAccessor;
-
- ///
- /// 构造函数
- ///
- ///
- public ShardingTableScopeFactory(IShardingTableAccessor shardingTableAccessor)
- {
- _shardingTableAccessor = shardingTableAccessor;
- }
- ///
- /// 创建环境
- ///
- ///
- public ShardingTableScope CreateScope()
- {
- _shardingTableAccessor.Context = null;
- return new ShardingTableScope(_shardingTableAccessor);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ShardingCore/Extensions/ShardingExtension.cs b/src/ShardingCore/Extensions/ShardingExtension.cs
new file mode 100644
index 00000000..798056a2
--- /dev/null
+++ b/src/ShardingCore/Extensions/ShardingExtension.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ShardingCore.Exceptions;
+using ShardingCore.Sharding.Abstractions;
+
+namespace ShardingCore.Extensions
+{
+ /*
+ * @Author: xjm
+ * @Description:
+ * @Date: 2021/8/15 16:12:27
+ * @Ver: 1.0
+ * @Email: 326308290@qq.com
+ */
+ ///
+ ///
+ ///
+ public static class ShardingExtension
+ {
+ private static readonly string ShardingTableDbContextFormat = $"sharding_{Guid.NewGuid():n}_";
+ ///
+ /// 获取分表的tail
+ ///
+ ///
+ ///
+ public static string GetShardingTableDbContextTail(this IShardingTableDbContext dbContext)
+ {
+ if (string.IsNullOrWhiteSpace(dbContext.ModelChangeKey))
+ throw new ShardingCoreException($"cant found ModelChangeKey in {dbContext.GetType().FullName}");
+ return dbContext.ModelChangeKey.Replace(ShardingTableDbContextFormat, string.Empty);
+
+ }
+ ///
+ /// 设置分表的tail
+ ///
+ ///
+ ///
+ public static void SetShardingTableDbContextTail(this IShardingTableDbContext dbContext, string tail)
+ {
+ if (!string.IsNullOrWhiteSpace(dbContext.ModelChangeKey))
+ throw new ShardingCoreException($"repeat set ModelChangeKey in {dbContext.GetType().FullName}");
+ dbContext.ModelChangeKey = $"{ShardingTableDbContextFormat}{tail}";
+ }
+ }
+}
diff --git a/src/ShardingCore/Sharding/AbstractShardingDbContext.cs b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs
new file mode 100644
index 00000000..a09de2da
--- /dev/null
+++ b/src/ShardingCore/Sharding/AbstractShardingDbContext.cs
@@ -0,0 +1,470 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.ChangeTracking;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage;
+using ShardingCore.Core;
+using ShardingCore.Core.VirtualRoutes.TableRoutes;
+using ShardingCore.Core.VirtualTables;
+using ShardingCore.DbContexts;
+using ShardingCore.Extensions;
+using ShardingCore.Sharding.Abstractions;
+
+namespace ShardingCore.Sharding
+{
+ /*
+ * @Author: xjm
+ * @Description:
+ * @Date: Saturday, 14 August 2021 09:57:08
+ * @Email: 326308290@qq.com
+ */
+ ///
+ /// 分表分库的dbcontext
+ ///
+ ///
+ public abstract class AbstractShardingDbContext : DbContext, IShardingDbContext where T : DbContext
+ {
+ private readonly string EMPTY_SHARDING_TAIL_ID = Guid.NewGuid().ToString("n");
+ private readonly ConcurrentDictionary _dbContextCaches = new ConcurrentDictionary();
+ private readonly IVirtualTableManager _virtualTableManager;
+ private readonly IShardingDbContextFactory _shardingDbContextFactory;
+ public AbstractShardingDbContext(DbContextOptions options) : base(options)
+ {
+ _shardingDbContextFactory = ShardingContainer.GetService();
+ }
+ public DbContext GetDbContext(bool track, string tail)
+ {
+ if (!_dbContextCaches.TryGetValue(tail, out var dbContext))
+ {
+ dbContext = _shardingDbContextFactory.Create(track ? this.Database.GetDbConnection() : null, tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail); ;
+ _dbContextCaches.TryAdd(tail, dbContext);
+ }
+
+ //if (IsOpenTransaction)
+ //{
+ // _dbTransaction.Use(dbContext);
+ //}
+
+ return dbContext;
+ }
+
+ public bool IsBeginTransaction => Database.CurrentTransaction != null;
+ public DbContext CreateGenericDbContext(T entity) where T : class
+ {
+ var tail = EMPTY_SHARDING_TAIL_ID;
+ if (entity.IsShardingTable())
+ {
+ var physicTable = _virtualTableManager.GetVirtualTable(entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0];
+ tail = physicTable.Tail;
+ }
+
+ return GetDbContext(true, tail);
+ }
+
+ public override EntityEntry Add(object entity)
+ {
+ return CreateGenericDbContext(entity).Add(entity);
+ }
+
+ public override EntityEntry Add(TEntity entity)
+ {
+ return CreateGenericDbContext(entity).Add(entity);
+ }
+
+ public override ValueTask> AddAsync(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
+ {
+ return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
+ }
+
+ public override ValueTask AddAsync(object entity, CancellationToken cancellationToken = new CancellationToken())
+ {
+ return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
+ }
+
+ public override void AddRange(params object[] entities)
+ {
+ 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