This commit is contained in:
xuejmnet 2021-08-21 00:09:02 +08:00
parent 310dca2c17
commit 436ff1de22
9 changed files with 113 additions and 54 deletions

View File

@ -198,6 +198,18 @@ Oracle | 支持 | 未测试
op.UseShardingDbContextOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger));
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
});
// //不支持MARS不支持追踪的
// services.AddShardingDbContext<DefaultShardingDbContext, DefaultTableDbContext>(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx2;Integrated Security=True;MultipleActiveResultSets=True;")
// ,op =>
// {
// op.EnsureCreatedWithOutShardingTable = true;
// op.CreateShardingTableOnStart = true;
// op.UseShardingConnOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger));
// op.UseShardingConnStrOptions((connstr, builder) => builder.UseSqlServer(connstr).UseLoggerFactory(efLogger));
// op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
// });
}
```

View File

@ -29,9 +29,19 @@ namespace Sample.SqlServer
{
op.EnsureCreatedWithOutShardingTable = true;
op.CreateShardingTableOnStart = true;
op.UseShardingDbContextOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger));
op.UseShardingConnOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger));
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
});
// //不支持MARS不支持追踪的
// services.AddShardingDbContext<DefaultShardingDbContext, DefaultTableDbContext>(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx2;Integrated Security=True;MultipleActiveResultSets=True;")
// ,op =>
// {
// op.EnsureCreatedWithOutShardingTable = true;
// op.CreateShardingTableOnStart = true;
// op.UseShardingConnOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger));
// op.UseShardingConnStrOptions((connstr, builder) => builder.UseSqlServer(connstr).UseLoggerFactory(efLogger));
// op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
// });
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@ -43,7 +43,7 @@ namespace ShardingCore
//添加创建TActualDbContext 的 创建者
var config = new ShardingDbContextOptionsBuilderConfig<TShardingDbContext>(shardingConfigOptions.ShardingDbContextOptionsCreator);
var config = new ShardingDbContextOptionsBuilderConfig<TShardingDbContext>(shardingConfigOptions.ShardingDbContextConnectionOptionsCreator,shardingConfigOptions.ShardingDbContextStringOptionsCreator);
services.AddSingleton<IShardingDbContextOptionsBuilderConfig, ShardingDbContextOptionsBuilderConfig<TShardingDbContext>>(sp=> config);
//添加创建TActualDbContext创建者

View File

@ -16,6 +16,8 @@ namespace ShardingCore
public interface IShardingDbContextOptionsBuilderConfig
{
Type ShardingDbContextType { get; }
bool SupportMARS { get; }
DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder);
DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, DbContextOptionsBuilder dbContextOptionsBuilder);
}
}

View File

@ -49,19 +49,17 @@ namespace ShardingCore.Sharding
_shardingDbContextOptionsBuilderConfig = ShardingContainer
.GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>()
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType);
}
public abstract Type ShardingDbContextType { get; }
public Type ActualDbContextType => typeof(T);
private DbContextOptionsBuilder<T> CreateDbContextOptionBuilder()
{
Type type = typeof(DbContextOptionsBuilder<>);
type = type.MakeGenericType(ActualDbContextType);
return (DbContextOptionsBuilder<T>)Activator.CreateInstance(type);
return (DbContextOptionsBuilder<T>) Activator.CreateInstance(type);
}
private DbContextOptions<T> GetDbContextOptions()
@ -71,6 +69,13 @@ namespace ShardingCore.Sharding
_shardingDbContextOptionsBuilderConfig.UseDbContextOptionsBuilder(dbConnection, dbContextOptionBuilder);
return dbContextOptionBuilder.Options;
}
private DbContextOptions<T> GetParallelDbContextOptions()
{
var dbContextOptionBuilder = CreateDbContextOptionBuilder();
var connectionString = Database.GetDbConnection().ConnectionString;
_shardingDbContextOptionsBuilderConfig.UseDbContextOptionsBuilder(connectionString, dbContextOptionBuilder);
return dbContextOptionBuilder.Options;
}
private ShardingDbContextOptions CreateSameShardingDbContextOptions(string tail)
{
@ -84,22 +89,36 @@ namespace ShardingCore.Sharding
}
}
}
return new ShardingDbContextOptions(_dbContextOptions, tail);
}
public DbContext GetDbContext(bool track, string tail)
private ShardingDbContextOptions CreateParallelShardingDbContextOptions(string tail)
{
if (!_dbContextCaches.TryGetValue(tail, out var dbContext))
return new ShardingDbContextOptions(GetParallelDbContextOptions(), tail);
}
private bool SupportMARS => _shardingDbContextOptionsBuilderConfig.SupportMARS;
public DbContext GetDbContext(bool isQuery, string tail)
{
if (SupportMARS || !isQuery)
{
dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, CreateSameShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail));
_dbContextCaches.TryAdd(tail, dbContext);
if (!_dbContextCaches.TryGetValue(tail, out var dbContext))
{
dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, CreateSameShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail));
_dbContextCaches.TryAdd(tail, dbContext);
}
return dbContext;
}
else
{
return _shardingDbContextFactory.Create(ShardingDbContextType, CreateParallelShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail));
}
return dbContext;
}
public bool IsBeginTransaction => Database.CurrentTransaction != null;
public DbContext CreateGenericDbContext<T>(T entity) where T : class
{
var tail = EMPTY_SHARDING_TAIL_ID;
@ -109,7 +128,7 @@ namespace ShardingCore.Sharding
tail = physicTable.Tail;
}
return GetDbContext(true, tail);
return GetDbContext(false, tail);
}
public bool TryOpen()
@ -135,7 +154,7 @@ namespace ShardingCore.Sharding
}
#if !EFCORE2
public override ValueTask<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
{
return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
@ -147,7 +166,6 @@ namespace ShardingCore.Sharding
}
#endif
#if EFCORE2
public override Task<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
{
return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
@ -179,7 +197,6 @@ namespace ShardingCore.Sharding
public override void AddRange(IEnumerable<object> entities)
{
var groups = entities.Select(o =>
{
var dbContext = CreateGenericDbContext(o);
@ -198,7 +215,6 @@ namespace ShardingCore.Sharding
public override async Task AddRangeAsync(params object[] entities)
{
var groups = entities.Select(o =>
{
var dbContext = CreateGenericDbContext(o);
@ -217,7 +233,6 @@ namespace ShardingCore.Sharding
public override async Task AddRangeAsync(IEnumerable<object> entities, CancellationToken cancellationToken = new CancellationToken())
{
var groups = entities.Select(o =>
{
var dbContext = CreateGenericDbContext(o);
@ -395,16 +410,17 @@ namespace ShardingCore.Sharding
{
Database.BeginTransaction();
}
int i = 0;
try
{
foreach (var dbContextCache in _dbContextCaches)
{
dbContextCache.Value.Database.UseTransaction(Database.CurrentTransaction.GetDbTransaction());
i += dbContextCache.Value.SaveChanges();
}
if (!isBeginTransaction)
Database.CurrentTransaction.Commit();
}
@ -418,30 +434,30 @@ namespace ShardingCore.Sharding
dbContextCache.Value.Database.UseTransaction(null);
}
}
}
return i;
}
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
var isBeginTransaction = IsBeginTransaction;
//如果是内部开的事务就内部自己消化
if (!isBeginTransaction)
{
Database.BeginTransaction();
}
int i = 0;
try
{
foreach (var dbContextCache in _dbContextCaches)
{
dbContextCache.Value.Database.UseTransaction(Database.CurrentTransaction.GetDbTransaction());
i += dbContextCache.Value.SaveChanges(acceptAllChangesOnSuccess);
}
if (!isBeginTransaction)
Database.CurrentTransaction.Commit();
}
@ -456,36 +472,40 @@ namespace ShardingCore.Sharding
}
}
}
return i;
}
#if !EFCORE2
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
var isBeginTransaction = IsBeginTransaction;
//如果是内部开的事务就内部自己消化
if (!isBeginTransaction)
{
await Database.BeginTransactionAsync(cancellationToken);
}
int i = 0;
try
{
foreach (var dbContextCache in _dbContextCaches)
{
await dbContextCache.Value.Database.UseTransactionAsync(Database.CurrentTransaction.GetDbTransaction(), cancellationToken: cancellationToken);
i += await dbContextCache.Value.SaveChangesAsync(cancellationToken);
}
if (!isBeginTransaction)
await Database.CurrentTransaction.CommitAsync(cancellationToken);
}
finally
{
if (!isBeginTransaction) { }
if (!isBeginTransaction)
{
}
if (Database.CurrentTransaction != null)
{
await Database.CurrentTransaction.DisposeAsync();
@ -494,14 +514,12 @@ namespace ShardingCore.Sharding
await dbContextCache.Value.Database.UseTransactionAsync(null, cancellationToken: cancellationToken);
}
}
}
return i;
}
#endif
#if EFCORE2
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
@ -544,23 +562,23 @@ namespace ShardingCore.Sharding
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken())
{
var isBeginTransaction = IsBeginTransaction;
//如果是内部开的事务就内部自己消化
if (!isBeginTransaction)
{
await Database.BeginTransactionAsync(cancellationToken);
}
int i = 0;
try
{
foreach (var dbContextCache in _dbContextCaches)
{
await dbContextCache.Value.Database.UseTransactionAsync(Database.CurrentTransaction.GetDbTransaction(), cancellationToken: cancellationToken);
i += await dbContextCache.Value.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
if (!isBeginTransaction)
await Database.CurrentTransaction.CommitAsync(cancellationToken);
}
@ -576,13 +594,12 @@ namespace ShardingCore.Sharding
await dbContextCache.Value.Database.UseTransactionAsync(null, cancellationToken: cancellationToken);
}
}
}
return i;
}
#endif
#if EFCORE2
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken())
{
@ -636,6 +653,7 @@ namespace ShardingCore.Sharding
Console.WriteLine(e);
}
}
base.Dispose();
}
@ -657,6 +675,5 @@ namespace ShardingCore.Sharding
await base.DisposeAsync();
}
#endif
}
}

View File

@ -15,18 +15,18 @@ namespace ShardingCore.Sharding.Abstractions
{
Type ShardingDbContextType { get; }
/// <summary>
/// 真实的DbContext 类型
/// <EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD>DbContext <20><><EFBFBD><EFBFBD>
/// </summary>
Type ActualDbContextType { get;}
/// <summary>
/// 创建DbContext
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>DbContext
/// </summary>
/// <param name="track">true表示创建的dbcontext挂在当前的shardingdbcontext下无需管理生命周期false需要手动释放true not care dbcontext life, false need call dispose()</param>
/// <param name="track">true<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>dbcontext<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ǰ<EFBFBD><EFBFBD>shardingdbcontext<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>false<EFBFBD><EFBFBD>Ҫ<EFBFBD>ֶ<EFBFBD><EFBFBD>ͷţ<EFBFBD>true not care dbcontext life, false need call dispose()</param>
/// <param name="tail"></param>
/// <returns></returns>
DbContext GetDbContext(bool track,string tail);
DbContext GetDbContext(bool isQuery,string tail);
/// <summary>
/// 根据实体创建db context
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD>db context
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entity"></param>

View File

@ -16,16 +16,26 @@ namespace ShardingCore.Sharding
*/
public class ShardingDbContextOptionsBuilderConfig<TShardingDbContext> : IShardingDbContextOptionsBuilderConfig where TShardingDbContext : DbContext, IShardingDbContext
{
public ShardingDbContextOptionsBuilderConfig(Action<DbConnection, DbContextOptionsBuilder> shardingDbContextOptionsCreator)
public ShardingDbContextOptionsBuilderConfig(Action<DbConnection, DbContextOptionsBuilder> shardingDbContextConnectionOptionsCreator,Action<string, DbContextOptionsBuilder> shardingDbContextStringionOptionsCreator)
{
ShardingDbContextOptionsCreator = shardingDbContextOptionsCreator;
ShardingDbContextConnectionOptionsCreator = shardingDbContextConnectionOptionsCreator;
ShardingDbContextStringOptionsCreator = shardingDbContextStringionOptionsCreator;
}
public Action<DbConnection, DbContextOptionsBuilder> ShardingDbContextOptionsCreator { get; }
public Action<DbConnection, DbContextOptionsBuilder> ShardingDbContextConnectionOptionsCreator { get; }
public Action<string, DbContextOptionsBuilder> ShardingDbContextStringOptionsCreator { get; }
public Type ShardingDbContextType => typeof(TShardingDbContext);
public bool SupportMARS => ShardingDbContextStringOptionsCreator == null;
public DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder)
{
ShardingDbContextOptionsCreator(dbConnection, dbContextOptionsBuilder);
ShardingDbContextConnectionOptionsCreator(dbConnection, dbContextOptionsBuilder);
dbContextOptionsBuilder.UseInnerDbContextSharding<TShardingDbContext>();
return dbContextOptionsBuilder;
}
public DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, DbContextOptionsBuilder dbContextOptionsBuilder)
{
ShardingDbContextStringOptionsCreator(connectionString, dbContextOptionsBuilder);
dbContextOptionsBuilder.UseInnerDbContextSharding<TShardingDbContext>();
return dbContextOptionsBuilder;
}

View File

@ -20,15 +20,22 @@ namespace ShardingCore
* @Email: 326308290@qq.com
*/
public class ShardingConfigOption<TShardingDbContext, TActualDbContext> : IShardingConfigOption
where TActualDbContext : DbContext, IShardingTableDbContext
where TShardingDbContext : DbContext, IShardingTableDbContext<TActualDbContext>
where TActualDbContext : DbContext, IShardingTableDbContext
where TShardingDbContext : DbContext, IShardingTableDbContext<TActualDbContext>
{
private readonly Dictionary<Type, Type> _virtualRoutes = new Dictionary<Type, Type>();
public Action<DbConnection, DbContextOptionsBuilder> ShardingDbContextOptionsCreator { get; set; }
public void UseShardingDbContextOptions(Action<DbConnection, DbContextOptionsBuilder> shardingDbContextOptionsCreator)
public Action<DbConnection, DbContextOptionsBuilder> ShardingDbContextConnectionOptionsCreator { get; set; }
public void UseShardingConnOptions(Action<DbConnection, DbContextOptionsBuilder> shardingDbContextOptionsCreator)
{
ShardingDbContextOptionsCreator = shardingDbContextOptionsCreator ?? throw new ArgumentNullException(nameof(shardingDbContextOptionsCreator));
ShardingDbContextConnectionOptionsCreator = shardingDbContextOptionsCreator ?? throw new ArgumentNullException(nameof(shardingDbContextOptionsCreator));
}
public Action<string, DbContextOptionsBuilder> ShardingDbContextStringOptionsCreator { get; set; }
public void UseShardingConnStrOptions(Action<string, DbContextOptionsBuilder> shardingDbContextOptionsCreator)
{
ShardingDbContextStringOptionsCreator = shardingDbContextOptionsCreator ?? throw new ArgumentNullException(nameof(shardingDbContextOptionsCreator));
}
@ -44,7 +51,7 @@ namespace ShardingCore
var routeType = typeof(TRoute);
//获取类型
var genericVirtualRoute = routeType.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualTableRoute<>)
&& it.GetGenericArguments().Any());
&& it.GetGenericArguments().Any());
if (genericVirtualRoute == null)
throw new ArgumentException("add sharding route type error not assignable from IVirtualTableRoute<>.");
@ -69,15 +76,16 @@ namespace ShardingCore
/// 如果数据库不存在就创建并且创建表除了分表的
/// </summary>
public bool EnsureCreatedWithOutShardingTable { get; set; }
/// <summary>
/// 是否需要在启动时创建分表
/// </summary>
public bool? CreateShardingTableOnStart { get; set; }
/// <summary>
/// 忽略建表时的错误
/// </summary>
public bool? IgnoreCreateTableError { get; set; }
}
}
}
}

View File

@ -54,7 +54,7 @@ namespace ShardingCore.Test50
{
op.EnsureCreatedWithOutShardingTable = true;
op.CreateShardingTableOnStart = true;
op.UseShardingDbContextOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger));
op.UseShardingConnStrOptions((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger));
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
});
}