完成动态数据源,动态读写分离

This commit is contained in:
xuejiaming 2022-07-02 15:01:18 +08:00
parent d0420888bc
commit 91635d9451
6 changed files with 191 additions and 249 deletions

View File

@ -10,6 +10,7 @@ using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.DynamicDataSources;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables; using ShardingCore.Sharding.ParallelTables;
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions; using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
@ -32,6 +33,7 @@ namespace ShardingCore.Core.RuntimeContexts
IQueryTracker GetQueryTracker(); IQueryTracker GetQueryTracker();
IUnionAllMergeManager GetUnionAllMergeManager(); IUnionAllMergeManager GetUnionAllMergeManager();
IShardingPageManager GetShardingPageManager(); IShardingPageManager GetShardingPageManager();
IDataSourceInitializer GetDataSourceInitializer();
void GetOrCreateShardingRuntimeModel(DbContext dbContext); void GetOrCreateShardingRuntimeModel(DbContext dbContext);

View File

@ -13,6 +13,7 @@ using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.DynamicDataSources;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
using ShardingCore.Logger; using ShardingCore.Logger;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -119,6 +120,11 @@ namespace ShardingCore.Core.RuntimeContexts
return GetRequiredService<IShardingPageManager>(); return GetRequiredService<IShardingPageManager>();
} }
public IDataSourceInitializer GetDataSourceInitializer()
{
return GetRequiredService<IDataSourceInitializer>();
}
public void GetOrCreateShardingRuntimeModel(DbContext dbContext) public void GetOrCreateShardingRuntimeModel(DbContext dbContext)
{ {
if (isInitModeled) return; if (isInitModeled) return;

View File

@ -142,7 +142,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
/// <exception cref="ShardingCoreNotFoundException"></exception> /// <exception cref="ShardingCoreNotFoundException"></exception>
public IPhysicDataSource GetPhysicDataSource(string dataSourceName) public IPhysicDataSource GetPhysicDataSource(string dataSourceName)
{ {
Check.NotNull(dataSourceName, "data source name is null,plz confirm IShardingBootstrapper.Star()"); Check.NotNull(dataSourceName, $"data source name is null,plz confirm {dataSourceName} add in virtual data source");
var dataSource = _physicDataSourcePool.TryGet(dataSourceName); var dataSource = _physicDataSourcePool.TryGet(dataSourceName);
if (null == dataSource) if (null == dataSource)
throw new ShardingCoreNotFoundException($"data source:[{dataSourceName}]"); throw new ShardingCoreNotFoundException($"data source:[{dataSourceName}]");

View File

@ -9,8 +9,14 @@ using ShardingCore.TableCreator;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Core.VirtualRoutes.Abstractions; using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Logger; using ShardingCore.Logger;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.DynamicDataSources namespace ShardingCore.DynamicDataSources
{ {
@ -19,6 +25,8 @@ namespace ShardingCore.DynamicDataSources
private static readonly ILogger<DataSourceInitializer> _logger = private static readonly ILogger<DataSourceInitializer> _logger =
ShardingLoggerFactory.CreateLogger<DataSourceInitializer>(); ShardingLoggerFactory.CreateLogger<DataSourceInitializer>();
private readonly IShardingProvider _shardingProvider;
private readonly IDbContextCreator _dbContextCreator;
private readonly IShardingRouteConfigOptions _routeConfigOptions; private readonly IShardingRouteConfigOptions _routeConfigOptions;
private readonly IVirtualDataSource _virtualDataSource; private readonly IVirtualDataSource _virtualDataSource;
private readonly IRouteTailFactory _routeTailFactory; private readonly IRouteTailFactory _routeTailFactory;
@ -27,6 +35,8 @@ namespace ShardingCore.DynamicDataSources
private readonly IShardingTableCreator _tableCreator; private readonly IShardingTableCreator _tableCreator;
public DataSourceInitializer( public DataSourceInitializer(
IShardingProvider shardingProvider,
IDbContextCreator dbContextCreator,
IShardingRouteConfigOptions routeConfigOptions, IShardingRouteConfigOptions routeConfigOptions,
IVirtualDataSource virtualDataSource, IVirtualDataSource virtualDataSource,
IRouteTailFactory routeTailFactory, IRouteTailFactory routeTailFactory,
@ -34,6 +44,8 @@ namespace ShardingCore.DynamicDataSources
IEntityMetadataManager entityMetadataManager, IEntityMetadataManager entityMetadataManager,
IShardingTableCreator shardingTableCreator) IShardingTableCreator shardingTableCreator)
{ {
_shardingProvider = shardingProvider;
_dbContextCreator = dbContextCreator;
_routeConfigOptions = routeConfigOptions; _routeConfigOptions = routeConfigOptions;
_virtualDataSource = virtualDataSource; _virtualDataSource = virtualDataSource;
_routeTailFactory = routeTailFactory; _routeTailFactory = routeTailFactory;
@ -42,125 +54,109 @@ namespace ShardingCore.DynamicDataSources
_tableCreator = shardingTableCreator; _tableCreator = shardingTableCreator;
} }
public void InitConfigure(string dataSourceName) public void InitConfigure(string dataSourceName,bool createDatabase,bool createTable)
{ {
// // var createDatabase = !needCreateDatabase.HasValue || needCreateDatabase.Value; // var createDatabase = !needCreateDatabase.HasValue || needCreateDatabase.Value;
// //
// // if ((_routeConfigOptions.EnsureCreatedWithOutShardingTable || !isOnStart)&&createDatabase)
// // EnsureCreated(virtualDataSource, context, dataSourceName);
// // else if (_routeConfigOptions.CreateDataBaseOnlyOnStart.GetValueOrDefault()&& createDatabase)
// // {
// // EnsureCreateDataBaseOnly(context, dataSourceName);
// // }
// //
// // var tableEnsureManager = virtualDataSource.ConfigurationParams.TableEnsureManager; // if ((_routeConfigOptions.EnsureCreatedWithOutShardingTable || !isOnStart)&&createDatabase)
// // ////获取数据库存在的所有的表 // EnsureCreated(virtualDataSource, context, dataSourceName);
// // var existTables = tableEnsureManager?.GetExistTables(context, dataSourceName) ?? // else if (_routeConfigOptions.CreateDataBaseOnlyOnStart.GetValueOrDefault()&& createDatabase)
// // new HashSet<string>();
// var allShardingEntities = _entityMetadataManager.GetAllShardingEntities();
// foreach (var entityType in allShardingEntities)
// { // {
// //如果是默认数据源 //
// if (_virtualDataSource.IsDefault(dataSourceName))
// {
// if (_entityMetadataManager.IsShardingTable(entityType))
// {
// var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
// InitVirtualTable(virtualTable);
// }
// }
// else
// {
// //非默认数据源
// if (_entityMetadataManager.IsShardingDataSource(entityType))
// {
// var virtualDataSourceRoute = virtualDataSource.GetRoute(entityType);
// if (virtualDataSourceRoute.GetAllDataSourceNames().Contains(dataSourceName))
// {
// if (_entityMetadataManager.IsShardingTable(entityType))
// {
// var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
// //创建表
// InitVirtualTable(virtualTable);
// }
// }
// }
// }
// } // }
} using (var shardingScope = _shardingProvider.CreateScope())
{
using (var shellDbContext = _dbContextCreator.GetShellDbContext(shardingScope.ServiceProvider))
{
var isDefault = _virtualDataSource.IsDefault(dataSourceName);
if (createDatabase)
{
EnsureCreated(isDefault,shellDbContext,dataSourceName);
}
// private void InitVirtualTable(IVirtualTable virtualTable) if (createTable)
// { {
// foreach (var tail in virtualTable.GetVirtualRoute().GetTails()) var allShardingEntities = _entityMetadataManager.GetAllShardingEntities();
// { foreach (var entityType in allShardingEntities)
// var defaultPhysicTable = new DefaultPhysicTable(virtualTable, tail); {
// virtualTable.AddPhysicTable(defaultPhysicTable); //如果是默认数据源
// } if (_virtualDataSource.IsDefault(dataSourceName))
// } {
// if (_entityMetadataManager.IsShardingTable(entityType))
// private bool NeedCreateTable(EntityMetadata entityMetadata) {
// { var virtualTableRoute = _tableRouteManager.GetRoute(entityType);
// if (entityMetadata.AutoCreateTable.HasValue) CreateDataTable(dataSourceName, virtualTableRoute, new HashSet<string>());
// { }
// if (entityMetadata.AutoCreateTable.Value) }
// return entityMetadata.AutoCreateTable.Value; else
// else {
// { //非默认数据源
// if (entityMetadata.AutoCreateDataSourceTable.HasValue) if (_entityMetadataManager.IsShardingDataSource(entityType))
// return entityMetadata.AutoCreateDataSourceTable.Value; {
// } var virtualDataSourceRoute = _virtualDataSource.GetRoute(entityType);
// } if (virtualDataSourceRoute.GetAllDataSourceNames().Contains(dataSourceName))
// {
// if (entityMetadata.AutoCreateDataSourceTable.HasValue) if (_entityMetadataManager.IsShardingTable(entityType))
// { {
// if (entityMetadata.AutoCreateDataSourceTable.Value) var virtualTableRoute = _tableRouteManager.GetRoute(entityType);
// return entityMetadata.AutoCreateDataSourceTable.Value; CreateDataTable(dataSourceName, virtualTableRoute, new HashSet<string>());
// else }
// { }
// if (entityMetadata.AutoCreateTable.HasValue) }
// return entityMetadata.AutoCreateTable.Value; }
// } }
// } }
// }
// return _routeConfigOptions.CreateShardingTableOnStart.GetValueOrDefault(); }
// } }
// private void EnsureCreated(bool isDefault, DbContext context,
// private void EnsureCreated(IVirtualDataSource<TShardingDbContext> virtualDataSource, DbContext context, string dataSourceName)
// string dataSourceName) {
// { if (context is IShardingDbContext shardingDbContext)
// if (context is IShardingDbContext shardingDbContext) {
// { using (var dbContext =
// using (var dbContext = shardingDbContext.GetDbContext(dataSourceName, false,
// shardingDbContext.GetDbContext(dataSourceName, false, _routeTailFactory.Create(string.Empty, false)))
// _routeTailFactory.Create(string.Empty, false))) {
// { if (isDefault)
// var isDefault = virtualDataSource.IsDefault(dataSourceName); {
// dbContext.RemoveDbContextRelationModelThatIsShardingTable();
// if (isDefault) }
// { else
// dbContext.RemoveDbContextRelationModelThatIsShardingTable(); {
// } dbContext.RemoveDbContextAllRelationModelThatIsNoSharding();
// else }
// {
// dbContext.RemoveDbContextAllRelationModelThatIsNoSharding(); dbContext.Database.EnsureCreated();
// } }
// }
// dbContext.Database.EnsureCreated(); else
// } {
// } throw new ShardingCoreInvalidOperationException(
// } $"{nameof(IDbContextCreator)}.{nameof(IDbContextCreator.GetShellDbContext)} db context type not impl {nameof(IShardingDbContext)}");
// }
// private void EnsureCreateDataBaseOnly(DbContext context, string dataSourceName) }
// { private void CreateDataTable(string dataSourceName, IVirtualTableRoute tableRoute, ISet<string> existTables)
// if (context is IShardingDbContext shardingDbContext) {
// { var entityMetadata = tableRoute.EntityMetadata;
// using (var dbContext = shardingDbContext.GetDbContext(dataSourceName, false, foreach (var tail in tableRoute.GetTails())
// _routeTailFactory.Create(string.Empty, false))) {
// { try
// dbContext.RemoveDbContextAllRelationModel(); {
// dbContext.Database.EnsureCreated(); //添加物理表
// } if (!existTables.Contains(entityMetadata.LogicTableName))
// } _tableCreator.CreateTable(dataSourceName, entityMetadata.EntityType, tail);
// } }
catch (Exception e)
{
if (!_routeConfigOptions.IgnoreCreateTableError.GetValueOrDefault())
{
_logger.LogWarning(e,
$"table :{entityMetadata.LogicTableName}{entityMetadata.TableSeparator}{tail} will created.");
}
}
}
}
} }
} }

View File

@ -1,20 +1,15 @@
using System; 
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.DynamicDataSources namespace ShardingCore.DynamicDataSources
{ {
public interface IDataSourceInitializer public interface IDataSourceInitializer
{ {
/// <summary> /// <summary>
/// /// 动态初始化数据源仅创建
/// </summary> /// </summary>
/// <param name="dataSourceName"></param> /// <param name="dataSourceName"></param>
void InitConfigure( string dataSourceName); /// <param name="createDatabase"></param>
/// <param name="createTable"></param>
void InitConfigure( string dataSourceName,bool createDatabase,bool createTable);
} }
} }

View File

@ -1,123 +1,66 @@
// using System; using System;
// using System.Collections.Generic; using System.Collections.Generic;
// using System.Linq; using System.Linq;
// using System.Text; using System.Text;
// using System.Threading.Tasks; using System.Threading.Tasks;
// using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
// using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Core.RuntimeContexts;
// using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
// using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
// using ShardingCore.DynamicDataSources; using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
// using ShardingCore.Exceptions; using ShardingCore.DynamicDataSources;
// using ShardingCore.Sharding.Abstractions; using ShardingCore.Exceptions;
// using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions; using ShardingCore.Sharding.Abstractions;
// using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
// namespace ShardingCore.Helpers
// { namespace ShardingCore.Helpers
// public class DynamicShardingHelper {
// { public class DynamicShardingHelper
// private DynamicShardingHelper() {
// { private DynamicShardingHelper()
// throw new InvalidOperationException($"{nameof(DynamicShardingHelper)} create instance"); {
// } throw new InvalidOperationException($"{nameof(DynamicShardingHelper)} create instance");
// /// <summary> }
// /// 动态添加虚拟数据源配置
// /// </summary> /// <summary>
// /// <typeparam name="TShardingDbContext"></typeparam> /// 动态添加数据源
// /// <param name="configurationParams"></param> /// </summary>
// /// <returns></returns> /// <typeparam name="TShardingDbContext"></typeparam>
// public static bool DynamicAppendVirtualDataSourceConfig<TShardingDbContext>( /// <param name="shardingRuntimeContext"></param>
// IVirtualDataSourceConfigurationParams<TShardingDbContext> configurationParams) /// <param name="dataSourceName"></param>
// where TShardingDbContext : DbContext, IShardingDbContext /// <param name="connectionString"></param>
// { /// <param name="createDatabase"></param>
// var virtualDataSourceManager = ShardingContainer.GetRequiredVirtualDataSourceManager<TShardingDbContext>(); /// <param name="createTable"></param>
// if (virtualDataSourceManager.AddVirtualDataSource(configurationParams)) public static void DynamicAppendDataSource<TShardingDbContext>(IShardingRuntimeContext shardingRuntimeContext, string dataSourceName, string connectionString,bool createDatabase,bool createTable) where TShardingDbContext : DbContext, IShardingDbContext
// { {
// virtualDataSourceManager.SetDefaultIfMultiConfiguration(); var virtualDataSource = shardingRuntimeContext.GetVirtualDataSource();
// var dataSourceInitializer = ShardingContainer.GetService<IDataSourceInitializer<TShardingDbContext>>(); virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceName, connectionString, false));
// var virtualDataSource = virtualDataSourceManager.GetVirtualDataSource(configurationParams.ConfigId); var dataSourceInitializer = shardingRuntimeContext.GetDataSourceInitializer();
// foreach (var dataSource in virtualDataSource.GetDataSources()) dataSourceInitializer.InitConfigure(dataSourceName,createDatabase,createTable);
// { }
// var dataSourceName = dataSource.Key;
// var connectionString = dataSource.Value; /// <summary>
// dataSourceInitializer.InitConfigure(virtualDataSource, dataSourceName, connectionString, false); /// 动态添加读写分离链接字符串
// } /// </summary>
// /// <typeparam name="TShardingDbContext"></typeparam>
// return true; /// <param name="shardingRuntimeContext"></param>
// } /// <param name="dataSourceName"></param>
// /// <param name="connectionString"></param>
// return false; /// <param name="readNodeName"></param>
// } /// <exception cref="ShardingCoreInvalidOperationException"></exception>
// /// <summary> public static void DynamicAppendReadWriteConnectionString<TShardingDbContext>(IShardingRuntimeContext shardingRuntimeContext, string dataSourceName,
// /// 动态添加数据源 string connectionString, string readNodeName=null) where TShardingDbContext : DbContext, IShardingDbContext
// /// </summary> {
// /// <typeparam name="TShardingDbContext"></typeparam> var virtualDataSource = shardingRuntimeContext.GetVirtualDataSource();
// /// <param name="virtualDataSource"></param> if (virtualDataSource.ConnectionStringManager is IReadWriteConnectionStringManager
// /// <param name="dataSourceName"></param> readWriteAppendConnectionString)
// /// <param name="connectionString"></param> {
// /// <param name="createDatabase"></param> readWriteAppendConnectionString.AddReadConnectionString(dataSourceName, connectionString, readNodeName);
// /// <param name="createTable"></param> return;
// public static void DynamicAppendDataSource<TShardingDbContext>(IVirtualDataSource<TShardingDbContext> virtualDataSource, string dataSourceName, string connectionString,bool? createDatabase=null,bool? createTable=null) where TShardingDbContext : DbContext, IShardingDbContext }
// {
// var defaultDataSourceInitializer = ShardingContainer.GetService<IDataSourceInitializer<TShardingDbContext>>(); throw new ShardingCoreInvalidOperationException(
// virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceName, connectionString, false)); $"{virtualDataSource.ConnectionStringManager.GetType()} cant support add read connection string");
// defaultDataSourceInitializer.InitConfigure(virtualDataSource, dataSourceName, connectionString, false,createDatabase,createTable); }
// } }
// /// <summary> }
// /// 动态添加数据源
// /// </summary>
// /// <typeparam name="TShardingDbContext"></typeparam>
// /// <param name="configId"></param>
// /// <param name="dataSourceName"></param>
// /// <param name="connectionString"></param>
// /// <param name="createDatabase"></param>
// /// <param name="createTable"></param>
// public static void DynamicAppendDataSource<TShardingDbContext>(string configId, string dataSourceName, string connectionString, bool? createDatabase = null, bool? createTable = null) where TShardingDbContext : DbContext, IShardingDbContext
// {
// var defaultDataSourceInitializer = ShardingContainer.GetService<IDataSourceInitializer<TShardingDbContext>>();
// var virtualDataSourceManager = ShardingContainer.GetService<IVirtualDataSourceManager<TShardingDbContext>>();
//
// var virtualDataSource = virtualDataSourceManager.GetVirtualDataSource(configId);
// virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceName, connectionString, false));
// defaultDataSourceInitializer.InitConfigure(virtualDataSource, dataSourceName, connectionString, false, createDatabase, createTable);
// }
//
// /// <summary>
// /// 动态添加读写分离链接字符串
// /// </summary>
// /// <typeparam name="TShardingDbContext"></typeparam>
// /// <param name="virtualDataSource"></param>
// /// <param name="dataSourceName"></param>
// /// <param name="connectionString"></param>
// /// <param name="readNodeName"></param>
// /// <exception cref="ShardingCoreInvalidOperationException"></exception>
// public static void DynamicAppendReadWriteConnectionString<TShardingDbContext>(IVirtualDataSource<TShardingDbContext> virtualDataSource, string dataSourceName,
// string connectionString, string readNodeName=null) where TShardingDbContext : DbContext, IShardingDbContext
// {
// if (virtualDataSource.ConnectionStringManager is IReadWriteConnectionStringManager
// readWriteAppendConnectionString)
// {
// readWriteAppendConnectionString.AddReadConnectionString(dataSourceName, connectionString, readNodeName);
// return;
// }
//
// throw new ShardingCoreInvalidOperationException(
// $"{virtualDataSource.ConnectionStringManager.GetType()} cant support add read connection string");
// }
// /// <summary>
// /// 动态添加读写分离链接字符串
// /// </summary>
// /// <typeparam name="TShardingDbContext"></typeparam>
// /// <param name="configId"></param>
// /// <param name="dataSourceName"></param>
// /// <param name="connectionString"></param>
// /// <param name="readNodeName"></param>
// public static void DynamicAppendReadWriteConnectionString<TShardingDbContext>(string configId, string dataSourceName,
// string connectionString, string readNodeName = null) where TShardingDbContext : DbContext, IShardingDbContext
// {
// var virtualDataSourceManager = ShardingContainer.GetRequiredVirtualDataSourceManager<TShardingDbContext>();
// var virtualDataSource = virtualDataSourceManager.GetVirtualDataSource(configId);
// DynamicAppendReadWriteConnectionString(virtualDataSource, dataSourceName, connectionString, readNodeName);
// }
// }
// }