完成多配置sharding编译[#73]

This commit is contained in:
xuejiaming 2022-01-06 14:51:01 +08:00
parent 819b4711af
commit c1de855bb9
81 changed files with 1766 additions and 523 deletions

View File

@ -129,7 +129,7 @@ namespace ShardingCore6x
_streamMergeContextFactory =
ShardingContainer.GetService<IStreamMergeContextFactory<DefaultShardingDbContext>>();
_actualConnectionStringManager = new ActualConnectionStringManager<DefaultShardingDbContext>();
_virtualDataSource = ShardingContainer.GetService<IVirtualDataSource<DefaultShardingDbContext>>();
_virtualDataSource = ShardingContainer.GetRequiredVirtualDataSourceManager<DefaultShardingDbContext>().GetVirtualDataSource();
_dataSourceRouteRuleEngineFactory = ShardingContainer.GetService<IDataSourceRouteRuleEngineFactory<DefaultShardingDbContext>>();
_tableRouteRuleEngineFactory = ShardingContainer.GetService<ITableRouteRuleEngineFactory<DefaultShardingDbContext>>();

View File

@ -8,6 +8,7 @@ using Sample.SqlServer.Domain.Entities;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Extensions;
@ -20,17 +21,17 @@ namespace Sample.SqlServer.Controllers
public class CreateTableController : ControllerBase
{
private readonly IShardingTableCreator<DefaultShardingDbContext> _tableCreator;
private readonly IVirtualDataSource<DefaultShardingDbContext> _virtualDataSource;
private readonly IVirtualDataSourceManager<DefaultShardingDbContext> _virtualDataSourceManager;
private readonly IVirtualTableManager<DefaultShardingDbContext> _virtualTableManager;
private readonly IEntityMetadataManager<DefaultShardingDbContext> _entityMetadataManager;
public CreateTableController(IShardingTableCreator<DefaultShardingDbContext> tableCreator,
IVirtualDataSource<DefaultShardingDbContext> virtualDataSource,
IVirtualDataSourceManager<DefaultShardingDbContext> virtualDataSourceManager,
IVirtualTableManager<DefaultShardingDbContext> virtualTableManager,
IEntityMetadataManager<DefaultShardingDbContext> entityMetadataManager)
{
_tableCreator = tableCreator;
_virtualDataSource = virtualDataSource;
_virtualDataSourceManager = virtualDataSourceManager;
_virtualTableManager = virtualTableManager;
_entityMetadataManager = entityMetadataManager;
}
@ -41,7 +42,7 @@ namespace Sample.SqlServer.Controllers
if (isShardingTable)
{
#region
var defaultDataSourceName = _virtualDataSource.DefaultDataSourceName;
var defaultDataSourceName = _virtualDataSourceManager.GetVirtualDataSource().DefaultDataSourceName;
try
{
_tableCreator.CreateTable<SysUserMod>(defaultDataSourceName, "09");

View File

@ -23,7 +23,8 @@ namespace Sample.SqlServerShardingAll.Controllers
public async Task<IActionResult> Query()
{
#region
var virtualDataSource = ShardingContainer.GetService<IVirtualDataSource<MyDbContext>>();
var virtualDataSource = ShardingContainer.GetRequiredVirtualDataSource<MyDbContext>();
var virtualDataSourceRoute1 = virtualDataSource.GetRoute(typeof(Order));
virtualDataSourceRoute1.AddDataSourceName("D");

View File

@ -22,7 +22,7 @@ namespace Sample.SqlServerShardingDataSource
public static void CreateSubDb(string dataSourceName, string connectionString)
{
var _entityMetadataManager = ShardingContainer.GetService<IEntityMetadataManager<MyDbContext>>();
var _virtualDataSource = ShardingContainer.GetService<IVirtualDataSource<MyDbContext>>();
var _virtualDataSource = ShardingContainer.GetRequiredVirtualDataSource<MyDbContext>();
var _virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<MyDbContext>>();
var _tableCreator = ShardingContainer.GetService<IShardingTableCreator<MyDbContext>>();

View File

@ -36,28 +36,64 @@ namespace Sample.SqlServerShardingTable
{
services.AddControllers();
services.AddShardingDbContext<MyDbContext>((conStr, builder) =>
//services.AddShardingDbContext<MyDbContext>((conStr, builder) =>
// {
// builder.UseSqlServer(conStr).UseLoggerFactory(efLogger);
// }).Begin(op =>
// {
// //如果您使用code-first建议选择false
// op.CreateShardingTableOnStart = true;
// //如果您使用code-first建议修改为fsle
// op.EnsureCreatedWithOutShardingTable = true;
// //当无法获取路由时会返回默认值而不是报错
// op.ThrowIfQueryRouteNotMatch = true;
// }).AddShardingTransaction((connection, builder) =>
// {
// builder.UseSqlServer(connection).UseLoggerFactory(efLogger);
// }).AddDefaultDataSource("ds0",
// "Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;")
// .AddShardingTableRoute(op =>
// {
// op.AddShardingTableRoute<SysUserVirtualTableRoute>();
// op.AddShardingTableRoute<OrderVirtualTableRoute>();
// op.AddShardingTableRoute<MultiShardingOrderVirtualTableRoute>();
// }).AddReadWriteSeparation(sp =>
// {
// return new Dictionary<string, IEnumerable<string>>()
// {
// {
// "ds0", new List<string>()
// {
// "Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;"
// }
// }
// };
// },ReadStrategyEnum.Loop,defaultEnable:true).End();
services.AddShardingDbContext<MyDbContext>().AddEntityConfig(op =>
{
//如果您使用code-first建议选择false
op.CreateShardingTableOnStart = true;
//如果您使用code-first建议修改为fsle
op.EnsureCreatedWithOutShardingTable = true;
//当无法获取路由时会返回默认值而不是报错
op.ThrowIfQueryRouteNotMatch = true;
op.AddShardingTableRoute<SysUserVirtualTableRoute>();
op.AddShardingTableRoute<OrderVirtualTableRoute>();
op.AddShardingTableRoute<MultiShardingOrderVirtualTableRoute>();
}).AddConfig(op =>
{
op.ConfigId = "a";
op.UseShardingQuery((conStr, builder) =>
{
builder.UseSqlServer(conStr).UseLoggerFactory(efLogger);
}).Begin(op =>
{
//如果您使用code-first建议选择false
op.CreateShardingTableOnStart = true;
//如果您使用code-first建议修改为fsle
op.EnsureCreatedWithOutShardingTable = true;
//当无法获取路由时会返回默认值而不是报错
op.ThrowIfQueryRouteNotMatch = true;
}).AddShardingTransaction((connection, builder) =>
});
op.UseShardingTransaction((connection, builder) =>
{
builder.UseSqlServer(connection).UseLoggerFactory(efLogger);
}).AddDefaultDataSource("ds0",
"Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;")
.AddShardingTableRoute(op =>
{
op.AddShardingTableRoute<SysUserVirtualTableRoute>();
op.AddShardingTableRoute<OrderVirtualTableRoute>();
op.AddShardingTableRoute<MultiShardingOrderVirtualTableRoute>();
}).AddReadWriteSeparation(sp =>
});
op.AddDefaultDataSource("ds0",
"Data Source=localhost;Initial Catalog=EFCoreShardingTableDB;Integrated Security=True;");
op.AddReadWriteSeparation(sp =>
{
return new Dictionary<string, IEnumerable<string>>()
{
@ -68,7 +104,8 @@ namespace Sample.SqlServerShardingTable
}
}
};
},ReadStrategyEnum.Loop,defaultEnable:true).End();
}, ReadStrategyEnum.Loop, defaultEnable: true);
}).EnsureConfig();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@ -21,6 +21,7 @@ using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
/*
* @Author: xjm
@ -42,14 +43,17 @@ namespace ShardingCore.Bootstrapers
private readonly string _virtualTableName;
private readonly Expression<Func<TEntity,bool>> _queryFilterExpression;
private readonly IShardingConfigOption<TShardingDbContext> _shardingConfigOption;
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
private readonly IVirtualDataSourceManager<TShardingDbContext> _virtualDataSourceManager;
private readonly IVirtualDataSourceRouteManager<TShardingDbContext> _virtualDataSourceRouteManager;
private readonly IVirtualTableManager<TShardingDbContext> _virtualTableManager;
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private readonly ILogger<EntityMetadataInitializer<TShardingDbContext, TEntity>> _logger;
public EntityMetadataInitializer(EntityMetadataEnsureParams entityMetadataEnsureParams
, IShardingConfigOption<TShardingDbContext> shardingConfigOption,
IVirtualDataSource<TShardingDbContext> virtualDataSource,IVirtualTableManager<TShardingDbContext> virtualTableManager,
IVirtualDataSourceManager<TShardingDbContext> virtualDataSourceManager,
IVirtualDataSourceRouteManager<TShardingDbContext> virtualDataSourceRouteManager,
IVirtualTableManager<TShardingDbContext> virtualTableManager,
IEntityMetadataManager<TShardingDbContext> entityMetadataManager,
ILogger<EntityMetadataInitializer<TShardingDbContext, TEntity>> logger
)
@ -58,7 +62,8 @@ namespace ShardingCore.Bootstrapers
_virtualTableName = entityMetadataEnsureParams.VirtualTableName;
_queryFilterExpression = entityMetadataEnsureParams.EntityType.GetAnnotations().FirstOrDefault(o=>o.Name== QueryFilter)?.Value as Expression<Func<TEntity, bool>>;
_shardingConfigOption = shardingConfigOption;
_virtualDataSource = virtualDataSource;
_virtualDataSourceManager = virtualDataSourceManager;
_virtualDataSourceRouteManager = virtualDataSourceRouteManager;
_virtualTableManager = virtualTableManager;
_entityMetadataManager = entityMetadataManager;
_logger = logger;
@ -92,8 +97,7 @@ namespace ShardingCore.Bootstrapers
{
entityMetadataDataSourceConfiguration.Configure(creatEntityMetadataDataSourceBuilder);
}
_virtualDataSource.AddVirtualDataSourceRoute(dataSourceRoute);
_virtualDataSourceRouteManager.AddVirtualDataSourceRoute(dataSourceRoute);
entityMetadata.CheckShardingDataSourceMetadata();
}

View File

@ -10,9 +10,12 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.TrackerManagers;
using ShardingCore.Core.VirtualDatabase;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
@ -54,25 +57,26 @@ namespace ShardingCore.Bootstrapers
/// </summary>
public class ShardingDbContextBootstrapper<TShardingDbContext> : IShardingDbContextBootstrapper where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly IShardingConfigOption<TShardingDbContext> _shardingConfigOption;
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
private readonly IVirtualDataSourceManager<TShardingDbContext> _virtualDataSourceManager;
private readonly IShardingEntityConfigOptions<TShardingDbContext> _entityConfigOptions;
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private readonly IParallelTableManager<TShardingDbContext> _parallelTableManager;
private readonly IDataSourceInitializer<TShardingDbContext> _dataSourceInitializer;
private readonly ITrackerManager<TShardingDbContext> _trackerManager;
private readonly Type _shardingDbContextType;
public ShardingDbContextBootstrapper(IShardingConfigOption<TShardingDbContext> shardingConfigOption,
public ShardingDbContextBootstrapper(
IVirtualDataSourceManager<TShardingDbContext> virtualDataSourceManager,
IShardingEntityConfigOptions<TShardingDbContext> entityConfigOptions,
IEntityMetadataManager<TShardingDbContext> entityMetadataManager,
IVirtualDataSource<TShardingDbContext> virtualDataSource,
IParallelTableManager<TShardingDbContext> parallelTableManager,
IDataSourceInitializer<TShardingDbContext> dataSourceInitializer,
ITrackerManager<TShardingDbContext> trackerManager)
{
_shardingConfigOption = shardingConfigOption;
_shardingDbContextType = typeof(TShardingDbContext);
_virtualDataSourceManager = virtualDataSourceManager;
_entityConfigOptions = entityConfigOptions;
_entityMetadataManager = entityMetadataManager;
_virtualDataSource= virtualDataSource;
_parallelTableManager = parallelTableManager;
_dataSourceInitializer = dataSourceInitializer;
_trackerManager = trackerManager;
@ -82,11 +86,9 @@ namespace ShardingCore.Bootstrapers
/// </summary>
public void Init()
{
_virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(_shardingConfigOption.DefaultDataSourceName, _shardingConfigOption.DefaultConnectionString, true));
InitializeEntityMetadata();
InitializeParallelTables();
InitializeConfigure();
_virtualDataSource.CheckVirtualDataSource();
}
private void InitializeEntityMetadata()
@ -102,8 +104,8 @@ namespace ShardingCore.Bootstrapers
var entityType = entity.ClrType;
_trackerManager.AddDbContextModel(entityType);
//entity.GetAnnotation("")
if (_shardingConfigOption.HasVirtualDataSourceRoute(entityType) ||
_shardingConfigOption.HasVirtualTableRoute(entityType))
if (_entityConfigOptions.HasVirtualDataSourceRoute(entityType) ||
_entityConfigOptions.HasVirtualTableRoute(entityType))
{
var entityMetadataInitializerType = typeof(EntityMetadataInitializer<,>).GetGenericType1(_shardingDbContextType, entityType);
@ -119,7 +121,7 @@ namespace ShardingCore.Bootstrapers
private void InitializeParallelTables()
{
foreach (var parallelTableGroupNode in _shardingConfigOption.GetParallelTableGroupNodes())
foreach (var parallelTableGroupNode in _entityConfigOptions.GetParallelTableGroupNodes())
{
var parallelTableComparerType = parallelTableGroupNode.GetEntities().FirstOrDefault(o => !_entityMetadataManager.IsShardingTable(o.Type));
if (parallelTableComparerType != null)
@ -133,12 +135,16 @@ namespace ShardingCore.Bootstrapers
private void InitializeConfigure()
{
var dataSources = _shardingConfigOption.GetDataSources();
foreach (var dataSourceKv in dataSources)
var allVirtualDataSources = _virtualDataSourceManager.GetAllVirtualDataSources();
foreach (var virtualDataSource in allVirtualDataSources)
{
var dataSourceName = dataSourceKv.Key;
var connectionString = dataSourceKv.Value;
_dataSourceInitializer.InitConfigure(dataSourceName, connectionString, true);
var dataSources = virtualDataSource.GetDataSources();
foreach (var dataSourceKv in dataSources)
{
var dataSourceName = dataSourceKv.Key;
var connectionString = dataSourceKv.Value;
_dataSourceInitializer.InitConfigure(virtualDataSource,dataSourceName, connectionString, true);
}
}
}
}

View File

@ -13,8 +13,7 @@ namespace ShardingCore.Core.EntityMetadatas
/// <typeparam name="TShardingDbContext"></typeparam>
public class DefaultEntityMetadataManager<TShardingDbContext> : IEntityMetadataManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly ConcurrentDictionary<Type, EntityMetadata> _caches =
new ConcurrentDictionary<Type, EntityMetadata>();
private readonly ConcurrentDictionary<Type, EntityMetadata> _caches =new ();
public bool AddEntityMetadata(EntityMetadata entityMetadata)
{
return _caches.TryAdd(entityMetadata.EntityType, entityMetadata);

View File

@ -25,7 +25,7 @@ namespace ShardingCore.Core.Internal.PriorityQueues {
}
public T Top() {
if (heapLength == 0) throw new OverflowException("queu is empty no element can return");
if (heapLength == 0) throw new OverflowException("queue is empty no element can return");
return buffer[0];
}
@ -38,7 +38,7 @@ namespace ShardingCore.Core.Internal.PriorityQueues {
}
public void Pop() {
if (heapLength == 0) throw new OverflowException("优先队列为空时无法执行出队操作");
if (heapLength == 0) throw new OverflowException("queue is empty no element can return");
--heapLength;
swap(0, heapLength);
Heap<T>.heapAdjustFromTop(buffer, 0, heapLength, descending,this.comparer);

View File

@ -0,0 +1,23 @@
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.Core.ShardingConfigurations.Abstractions
{
public interface IShardingConfigurationOptions
{
public void AddShardingGlobalConfigOptions(ShardingGlobalConfigOptions shardingGlobalConfigOptions);
public ShardingGlobalConfigOptions[] GetAllShardingGlobalConfigOptions();
}
public interface IShardingConfigurationOptions<TShardingDbContext> : IShardingConfigurationOptions where TShardingDbContext:DbContext,IShardingDbContext
{
}
}

View File

@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common;
using ShardingCore.DIExtensions;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
namespace ShardingCore.Core.ShardingConfigurations.ConfigBuilders
{
public class ShardingEntityConfigBuilder<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly ShardingCoreConfigBuilder<TShardingDbContext> _shardingCoreConfigBuilder;
public ShardingEntityConfigBuilder(ShardingCoreConfigBuilder<TShardingDbContext> shardingCoreConfigBuilder)
{
_shardingCoreConfigBuilder = shardingCoreConfigBuilder;
}
public ShardingEntityConfigBuilder<TShardingDbContext> AddConfig(Action<ShardingGlobalConfigOptions> shardingGlobalConfigOptionsConfigure)
{
var shardingGlobalConfigOptions = new ShardingGlobalConfigOptions();
shardingGlobalConfigOptionsConfigure?.Invoke(shardingGlobalConfigOptions);
if (string.IsNullOrWhiteSpace(shardingGlobalConfigOptions.ConfigId))
throw new ArgumentNullException(nameof(shardingGlobalConfigOptions.ConfigId));
if (string.IsNullOrWhiteSpace(shardingGlobalConfigOptions.DefaultDataSourceName))
throw new ArgumentNullException(
$"{nameof(shardingGlobalConfigOptions.DefaultDataSourceName)} plz call {nameof(ShardingGlobalConfigOptions.AddDefaultDataSource)}");
if (string.IsNullOrWhiteSpace(shardingGlobalConfigOptions.DefaultConnectionString))
throw new ArgumentNullException(
$"{nameof(shardingGlobalConfigOptions.DefaultConnectionString)} plz call {nameof(ShardingGlobalConfigOptions.AddDefaultDataSource)}");
if (shardingGlobalConfigOptions.ConnectionStringConfigure is null)
throw new ArgumentNullException($"plz call {nameof(shardingGlobalConfigOptions.UseShardingQuery)}");
if (shardingGlobalConfigOptions.ConnectionConfigure is null)
throw new ArgumentNullException(
$"plz call {nameof(shardingGlobalConfigOptions.UseShardingTransaction)}");
if (shardingGlobalConfigOptions.ReplaceShardingComparerFactory == null)
{
throw new ShardingCoreConfigException($"{nameof(shardingGlobalConfigOptions.ReplaceShardingComparerFactory)} is null");
}
if (shardingGlobalConfigOptions.MaxQueryConnectionsLimit <= 0)
throw new ArgumentException(
$"{nameof(shardingGlobalConfigOptions.MaxQueryConnectionsLimit)} should greater than and equal 1");
_shardingCoreConfigBuilder.ShardingGlobalConfigOptions.Add(shardingGlobalConfigOptions);
return this;
}
public IServiceCollection EnsureConfig()
{
return DoEnsureConfig(false, ShardingConfigurationStrategyEnum.ThrowIfNull);
}
public IServiceCollection EnsureMultiConfig(ShardingConfigurationStrategyEnum configurationStrategy= ShardingConfigurationStrategyEnum.ThrowIfNull)
{
return DoEnsureConfig(true, configurationStrategy);
}
private IServiceCollection DoEnsureConfig(bool isMultiConfig,
ShardingConfigurationStrategyEnum configurationStrategy)
{
if (_shardingCoreConfigBuilder.ShardingGlobalConfigOptions.IsEmpty())
throw new ArgumentException($"plz call {nameof(AddConfig)} at least once ");
if (!isMultiConfig)
{
if (_shardingCoreConfigBuilder.ShardingGlobalConfigOptions.Count > 1)
{
throw new ArgumentException($"call {nameof(AddConfig)} at most once ");
}
}
var services = _shardingCoreConfigBuilder.Services;
services.AddSingleton<IDbContextTypeCollector>(sp => new DbContextTypeCollector<TShardingDbContext>());
services.AddSingleton<IShardingEntityConfigOptions<TShardingDbContext>>(sp => _shardingCoreConfigBuilder.ShardingEntityConfigOptions);
services.AddSingleton(sp => _shardingCoreConfigBuilder.ShardingEntityConfigOptions);
if (!isMultiConfig)
{
services.AddSingleton<IShardingConfigurationOptions<TShardingDbContext>>(sp =>
{
var shardingSingleConfigurationOptions = new ShardingSingleConfigurationOptions<TShardingDbContext>();
shardingSingleConfigurationOptions.ShardingConfigurationStrategy = configurationStrategy;
shardingSingleConfigurationOptions.AddShardingGlobalConfigOptions(_shardingCoreConfigBuilder
.ShardingGlobalConfigOptions.First());
return shardingSingleConfigurationOptions;
});
}
else
{
services.AddSingleton<IShardingConfigurationOptions<TShardingDbContext>>(sp =>
{
var shardingMultiConfigurationOptions = new ShardingMultiConfigurationOptions<TShardingDbContext>();
shardingMultiConfigurationOptions.ShardingConfigurationStrategy = configurationStrategy;
foreach (var shardingGlobalConfigOptions in _shardingCoreConfigBuilder
.ShardingGlobalConfigOptions)
{
shardingMultiConfigurationOptions.AddShardingGlobalConfigOptions(shardingGlobalConfigOptions);
}
return shardingMultiConfigurationOptions;
});
}
services.AddInternalShardingCore();
return services;
}
}
}

View File

@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
namespace ShardingCore.Core.ShardingConfigurations
{
public interface IShardingEntityConfigOptions
{
/// <summary>
/// 如果数据库不存在就创建并且创建表除了分表的
/// </summary>
bool EnsureCreatedWithOutShardingTable { get; set; }
/// <summary>
/// 是否需要在启动时创建分表
/// </summary>
bool? CreateShardingTableOnStart { get; set; }
/// <summary>
/// 当查询遇到没有路由被命中时是否抛出错误
/// </summary>
bool ThrowIfQueryRouteNotMatch { get; set; }
/// <summary>
/// 忽略建表时的错误
/// </summary>
bool? IgnoreCreateTableError { get; set; }
bool? EnableTableRouteCompileCache { get; set; }
bool? EnableDataSourceRouteCompileCache { get; set; }
/// <summary>
/// 添加分表路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
void AddShardingDataSourceRoute<TRoute>() where TRoute : IVirtualDataSourceRoute;
void AddShardingDataSourceRoute(Type routeType);
/// <summary>
/// 添加分表路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
void AddShardingTableRoute<TRoute>() where TRoute : IVirtualTableRoute;
void AddShardingTableRoute(Type routeType);
bool HasVirtualTableRoute(Type entityType);
Type GetVirtualTableRouteType(Type entityType);
bool HasVirtualDataSourceRoute(Type entityType);
Type GetVirtualDataSourceRouteType(Type entityType);
ISet<Type> GetShardingTableRouteTypes();
ISet<Type> GetShardingDataSourceRouteTypes();
/// <summary>
/// 平行表
/// </summary>
bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode);
ISet<ParallelTableGroupNode> GetParallelTableGroupNodes();
}
public interface IShardingEntityConfigOptions<TShardingDbContext>: IShardingEntityConfigOptions where TShardingDbContext : DbContext, IShardingDbContext
{
}
public class ShardingEntityConfigOptions<TShardingDbContext> : IShardingEntityConfigOptions<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly Dictionary<Type, Type> _virtualDataSourceRoutes = new Dictionary<Type, Type>();
private readonly Dictionary<Type, Type> _virtualTableRoutes = new Dictionary<Type, Type>();
public readonly ISet<ParallelTableGroupNode> _parallelTables = new HashSet<ParallelTableGroupNode>();
/// <summary>
/// 如果数据库不存在就创建并且创建表除了分表的
/// </summary>
public bool EnsureCreatedWithOutShardingTable { get; set; }
/// <summary>
/// 是否需要在启动时创建分表
/// </summary>
public bool? CreateShardingTableOnStart { get; set; }
/// <summary>
/// 当查询遇到没有路由被命中时是否抛出错误
/// </summary>
public bool ThrowIfQueryRouteNotMatch { get; set; } = true;
public bool? EnableTableRouteCompileCache { get; set; }
public bool? EnableDataSourceRouteCompileCache { get; set; }
/// <summary>
/// 忽略建表时的错误
/// </summary>
public bool? IgnoreCreateTableError { get; set; } = true;
/// <summary>
/// 添加分表路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
public void AddShardingDataSourceRoute<TRoute>() where TRoute : IVirtualDataSourceRoute
{
var routeType = typeof(TRoute);
AddShardingDataSourceRoute(routeType);
}
public void AddShardingDataSourceRoute(Type routeType)
{
if (!routeType.IsVirtualDataSourceRoute())
throw new ShardingCoreInvalidOperationException(routeType.FullName);
//获取类型
var genericVirtualRoute = routeType.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualDataSourceRoute<>)
&& it.GetGenericArguments().Any());
if (genericVirtualRoute == null)
throw new ArgumentException("add sharding route type error not assignable from IVirtualDataSourceRoute<>.");
var shardingEntityType = genericVirtualRoute.GetGenericArguments()[0];
if (shardingEntityType == null)
throw new ArgumentException("add sharding table route type error not assignable from IVirtualDataSourceRoute<>");
if (!_virtualDataSourceRoutes.ContainsKey(shardingEntityType))
{
_virtualDataSourceRoutes.Add(shardingEntityType, routeType);
}
}
/// <summary>
/// 添加分表路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
public void AddShardingTableRoute<TRoute>() where TRoute : IVirtualTableRoute
{
var routeType = typeof(TRoute);
AddShardingTableRoute(routeType);
}
public void AddShardingTableRoute(Type routeType)
{
if (!routeType.IsIVirtualTableRoute())
throw new ShardingCoreInvalidOperationException(routeType.FullName);
//获取类型
var genericVirtualRoute = routeType.GetInterfaces().FirstOrDefault(it => it.IsInterface && it.IsGenericType && it.GetGenericTypeDefinition() == typeof(IVirtualTableRoute<>)
&& it.GetGenericArguments().Any());
if (genericVirtualRoute == null)
throw new ArgumentException("add sharding route type error not assignable from IVirtualTableRoute<>.");
var shardingEntityType = genericVirtualRoute.GetGenericArguments()[0];
if (shardingEntityType == null)
throw new ArgumentException("add sharding table route type error not assignable from IVirtualTableRoute<>");
if (!_virtualTableRoutes.ContainsKey(shardingEntityType))
{
_virtualTableRoutes.Add(shardingEntityType, routeType);
}
}
public bool HasVirtualTableRoute(Type entityType)
{
return _virtualTableRoutes.ContainsKey(entityType);
}
public Type GetVirtualTableRouteType(Type entityType)
{
if (!_virtualTableRoutes.ContainsKey(entityType))
throw new ArgumentException($"{entityType} not found IVirtualTableRoute");
return _virtualTableRoutes[entityType];
}
public bool HasVirtualDataSourceRoute(Type entityType)
{
return _virtualDataSourceRoutes.ContainsKey(entityType);
}
public Type GetVirtualDataSourceRouteType(Type entityType)
{
if (!_virtualDataSourceRoutes.ContainsKey(entityType))
throw new ArgumentException($"{entityType} not found IVirtualDataSourceRoute");
return _virtualDataSourceRoutes[entityType];
}
public ISet<Type> GetShardingTableRouteTypes()
{
return _virtualTableRoutes.Keys.ToHashSet();
}
public ISet<Type> GetShardingDataSourceRouteTypes()
{
return _virtualDataSourceRoutes.Keys.ToHashSet();
}
public bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode)
{
Check.NotNull(parallelTableGroupNode, $"{nameof(parallelTableGroupNode)}");
return _parallelTables.Add(parallelTableGroupNode);
}
public ISet<ParallelTableGroupNode> GetParallelTableGroupNodes()
{
return _parallelTables;
}
}
}

View File

@ -0,0 +1,111 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
namespace ShardingCore.Core.ShardingConfigurations
{
public class ShardingGlobalConfigOptions
{
/// <summary>
/// 配置id
/// </summary>
public string ConfigId { get; set; }
/// <summary>
/// 优先级
/// </summary>
public int Priority { get; set; }
public int MaxQueryConnectionsLimit { get; set; } = Environment.ProcessorCount;
public ConnectionModeEnum ConnectionMode { get; set; } = ConnectionModeEnum.SYSTEM_AUTO;
/// <summary>
/// 读写分离配置
/// </summary>
public ShardingReadWriteSeparationOptions ShardingReadWriteSeparationOptions { get; private set; }
/// <summary>
/// 默认数据源
/// </summary>
public string DefaultDataSourceName { get; private set; }
/// <summary>
/// 默认数据源链接字符串
/// </summary>
public string DefaultConnectionString { get; private set; }
/// <summary>
/// 添加默认数据源
/// </summary>
/// <param name="dataSourceName"></param>
/// <param name="connectionString"></param>
/// <exception cref="ArgumentNullException"></exception>
public void AddDefaultDataSource(string dataSourceName, string connectionString)
{
DefaultDataSourceName= dataSourceName?? throw new ArgumentNullException(nameof(dataSourceName));
DefaultConnectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
}
public Func<IServiceProvider, IDictionary<string, string>> DataSourcesConfigure { get; private set; }
/// <summary>
/// 添加额外数据源
/// </summary>
/// <param name="extraDataSourceConfigure"></param>
/// <exception cref="ArgumentNullException"></exception>
public void AddExtraDataSource(Func<IServiceProvider, IDictionary<string, string>> extraDataSourceConfigure)
{
DataSourcesConfigure= extraDataSourceConfigure ?? throw new ArgumentNullException(nameof(extraDataSourceConfigure));
}
/// <summary>
/// 添加读写分离配置
/// </summary>
/// <param name="readWriteSeparationConfigure"></param>
/// <param name="readStrategyEnum"></param>
/// <param name="defaultEnable"></param>
/// <param name="defaultPriority"></param>
/// <param name="readConnStringGetStrategy"></param>
/// <exception cref="ArgumentNullException"></exception>
public void AddReadWriteSeparation(
Func<IServiceProvider, IDictionary<string, IEnumerable<string>>> readWriteSeparationConfigure,
ReadStrategyEnum readStrategyEnum,
bool defaultEnable = false,
int defaultPriority = 10,
ReadConnStringGetStrategyEnum readConnStringGetStrategy = ReadConnStringGetStrategyEnum.LatestFirstTime)
{
ShardingReadWriteSeparationOptions = new ShardingReadWriteSeparationOptions();
ShardingReadWriteSeparationOptions.ReadWriteSeparationConfigure= readWriteSeparationConfigure ?? throw new ArgumentNullException(nameof(readWriteSeparationConfigure));
ShardingReadWriteSeparationOptions.ReadStrategy = readStrategyEnum;
ShardingReadWriteSeparationOptions.DefaultEnable=defaultEnable;
ShardingReadWriteSeparationOptions.DefaultPriority= defaultPriority;
ShardingReadWriteSeparationOptions.ReadConnStringGetStrategy= readConnStringGetStrategy;
}
public Action<DbConnection, DbContextOptionsBuilder> ConnectionConfigure { get; private set; }
public Action<string, DbContextOptionsBuilder> ConnectionStringConfigure { get; private set; }
public void UseShardingQuery(Action<string, DbContextOptionsBuilder> queryConfigure)
{
ConnectionStringConfigure = queryConfigure ?? throw new ArgumentNullException(nameof(queryConfigure));
}
public void UseShardingTransaction(Action<DbConnection, DbContextOptionsBuilder> transactionConfigure)
{
ConnectionConfigure = transactionConfigure ?? throw new ArgumentNullException(nameof(transactionConfigure));
}
public Func<IServiceProvider, IShardingComparer> ReplaceShardingComparerFactory { get; private set; } = sp => new CSharpLanguageShardingComparer();
/// <summary>
/// 替换默认的比较器
/// </summary>
/// <param name="newShardingComparerFactory"></param>
/// <exception cref="ArgumentNullException"></exception>
public void ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer> newShardingComparerFactory)
{
ReplaceShardingComparerFactory = newShardingComparerFactory ?? throw new ArgumentNullException(nameof(newShardingComparerFactory));
}
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.ShardingConfigurations
{
public class ShardingMultiConfigurationOptions<TShardingDbContext> : IShardingConfigurationOptions<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
public ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; set; } =
ShardingConfigurationStrategyEnum.ThrowIfNull;
private Dictionary<string, ShardingGlobalConfigOptions> _shardingGlobalConfigOptions = new ();
public void AddShardingGlobalConfigOptions(ShardingGlobalConfigOptions shardingGlobalConfigOptions)
{
if (_shardingGlobalConfigOptions.ContainsKey(shardingGlobalConfigOptions.ConfigId))
throw new ShardingCoreInvalidOperationException($"repeat add config id:[{shardingGlobalConfigOptions.ConfigId}]");
_shardingGlobalConfigOptions.Add(shardingGlobalConfigOptions.ConfigId, shardingGlobalConfigOptions);
}
public ShardingGlobalConfigOptions[] GetAllShardingGlobalConfigOptions()
{
return _shardingGlobalConfigOptions.Values.ToArray();
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using ShardingCore.Sharding.ReadWriteConfigurations;
namespace ShardingCore.Core.ShardingConfigurations
{
public class ShardingReadWriteSeparationOptions
{
public Func<IServiceProvider, IDictionary<string, IEnumerable<string>>> ReadWriteSeparationConfigure { get; set; }
public ReadStrategyEnum ReadStrategy { get; set; } = ReadStrategyEnum.Loop;
public bool DefaultEnable { get; set; } = false;
public int DefaultPriority { get; set; } = 10;
public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; set; } =
ReadConnStringGetStrategyEnum.LatestFirstTime;
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.ShardingConfigurations
{
public class ShardingSingleConfigurationOptions<TShardingDbContext> : IShardingConfigurationOptions<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
private ShardingGlobalConfigOptions _shardingGlobalConfigOptions;
public ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; set; } =
ShardingConfigurationStrategyEnum.ThrowIfNull;
public void AddShardingGlobalConfigOptions(ShardingGlobalConfigOptions shardingGlobalConfigOptions)
{
if (_shardingGlobalConfigOptions != null)
throw new ShardingCoreInvalidOperationException($"repeat add {nameof(ShardingGlobalConfigOptions)}");
_shardingGlobalConfigOptions= shardingGlobalConfigOptions;
}
public ShardingGlobalConfigOptions[] GetAllShardingGlobalConfigOptions()
{
return new[] { _shardingGlobalConfigOptions };
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
{
public abstract class AbstractVirtualDataSourceConfigurationParams<TShardingDbContext>:IVirtualDataSourceConfigurationParams<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
{
public abstract string ConfigId { get; }
public abstract int Priority { get; }
public abstract int MaxQueryConnectionsLimit { get; }
public abstract ConnectionModeEnum ConnectionMode { get; }
public abstract string DefaultDataSourceName { get; }
public abstract string DefaultConnectionString { get; }
public abstract IDictionary<string, string> ExtraDataSources { get; }
public abstract IDictionary<string, IEnumerable<string>> ReadWriteSeparationConfigs { get; }
public abstract ReadStrategyEnum? ReadStrategy { get; }
public abstract bool? ReadWriteDefaultEnable { get; }
public abstract int? ReadWriteDefaultPriority { get; }
public abstract ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; }
public abstract IShardingComparer ShardingComparer { get; }
public abstract DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
DbContextOptionsBuilder dbContextOptionsBuilder);
public abstract DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection,
DbContextOptionsBuilder dbContextOptionsBuilder);
public virtual bool UseReadWriteSeparation()
{
return ReadWriteSeparationConfigs.IsNotEmpty();
}
}
}

View File

@ -29,5 +29,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
/// </summary>
/// <returns></returns>
List<string> GetAllDataSourceNames();
IDictionary<string, string> GetDataSources();
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
{
public interface IVirtualDataSourceAccessor
{
VirtualDataSourceContext DataSourceContext { get; set; }
}
}

View File

@ -0,0 +1,65 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
using System.Collections.Generic;
using System.Data.Common;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
{
public interface IVirtualDataSourceConfigurationParams
{
/// <summary>
/// 配置id
/// </summary>
string ConfigId { get; }
/// <summary>
/// 优先级
/// </summary>
int Priority { get; }
int MaxQueryConnectionsLimit { get; }
ConnectionModeEnum ConnectionMode { get; }
/// <summary>
/// 默认数据源
/// </summary>
string DefaultDataSourceName { get; }
/// <summary>
/// 默认数据源链接字符串
/// </summary>
string DefaultConnectionString { get; }
IDictionary<string,string> ExtraDataSources { get; }
IDictionary<string, IEnumerable<string>> ReadWriteSeparationConfigs { get; }
ReadStrategyEnum? ReadStrategy { get; }
bool? ReadWriteDefaultEnable { get; }
int? ReadWriteDefaultPriority { get; }
/// <summary>
/// 读写分离链接字符串获取
/// </summary>
ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; }
IShardingComparer ShardingComparer { get; }
/// <summary>
/// 如何根据connectionString 配置 DbContextOptionsBuilder
/// </summary>
/// <param name="connectionString"></param>
/// <param name="dbContextOptionsBuilder"></param>
/// <returns></returns>
DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, DbContextOptionsBuilder dbContextOptionsBuilder);
/// <summary>
/// 如何根据dbConnection 配置DbContextOptionsBuilder
/// </summary>
/// <param name="dbConnection"></param>
/// <param name="dbContextOptionsBuilder"></param>
/// <returns></returns>
DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder);
bool UseReadWriteSeparation();
}
public interface IVirtualDataSourceConfigurationParams<TShardingDbContext> : IVirtualDataSourceConfigurationParams
where TShardingDbContext : DbContext, IShardingDbContext
{
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
{
public interface IVirtualDataSourceManager
{
bool IsMultiShardingConfiguration { get; }
ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; }
IVirtualDataSource GetVirtualDataSource();
List<IVirtualDataSource> GetAllVirtualDataSources();
/// <summary>
/// 创建分片配置scope
/// </summary>
/// <param name="configId"></param>
/// <returns></returns>
VirtualDataSourceScope CreateScope(string configId);
}
public interface IVirtualDataSourceManager<TShardingDbContext> : IVirtualDataSourceManager
where TShardingDbContext : DbContext, IShardingDbContext
{
IVirtualDataSource<TShardingDbContext> GetVirtualDataSource();
List<IVirtualDataSource<TShardingDbContext>> GetAllVirtualDataSources();
void AddVirtualDataSource(IVirtualDataSourceConfigurationParams<TShardingDbContext> configurationParams);
}
}

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
{
public interface IVirtualDataSourceRouteManager
{
/// <summary>
/// 获取当前数据源的路由
/// </summary>
/// <returns></returns>
IVirtualDataSourceRoute GetRoute(Type entityType);
/// <summary>
/// 添加分库路由
/// </summary>
/// <param name="virtualDataSourceRoute"></param>
/// <returns></returns>
/// <exception cref="ShardingCoreInvalidOperationException">对象未配置分库</exception>
bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute);
}
public interface IVirtualDataSourceRouteManager<TShardingDbContext> : IVirtualDataSourceRouteManager
where TShardingDbContext : DbContext, IShardingDbContext
{
IVirtualDataSourceRoute<TEntity> GetRoute<TEntity>() where TEntity:class;
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common
{
public enum ShardingConfigurationStrategyEnum
{
/// <summary>
/// 返回空
/// </summary>
ReturnNull = 1,
/// <summary>
/// 抛出异常
/// </summary>
ThrowIfNull = 1 << 1,
/// <summary>
/// 返回优先级最高的
/// </summary>
ReturnHighPriority = 1 << 2
}
}

View File

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
@ -19,10 +22,18 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
public interface IVirtualDataSource
{
string ConfigId { get; }
int Priority { get; }
IVirtualDataSourceConfigurationParams ConfigurationParams { get; }
IConnectionStringManager ConnectionStringManager { get; }
bool UseReadWriteSeparation { get; }
/// <summary>
/// 默认的数据源名称
/// </summary>
string DefaultDataSourceName { get; }
string DefaultConnectionString { get;}
IVirtualDataSourceRoute GetRoute(Type entityType);
/// <summary>
/// 路由到具体的物理数据源
/// </summary>
@ -31,12 +42,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
/// <returns>data source names</returns>
List<string> RouteTo(Type entityType, ShardingDataSourceRouteConfig routeRouteConfig);
/// <summary>
/// 获取当前数据源的路由
/// </summary>
/// <returns></returns>
IVirtualDataSourceRoute GetRoute(Type entityType);
/// <summary>
/// 获取默认的数据源信息
/// </summary>
@ -74,13 +79,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
/// <exception cref="ShardingCoreInvalidOperationException">重复添加默认数据源</exception>
bool AddPhysicDataSource(IPhysicDataSource physicDataSource);
/// <summary>
/// 添加分库路由
/// </summary>
/// <param name="virtualDataSourceRoute"></param>
/// <returns></returns>
/// <exception cref="ShardingCoreInvalidOperationException">对象未配置分库</exception>
bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute);
/// <summary>
/// 是否默认数据源
/// </summary>
@ -92,6 +90,22 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
/// </summary>
/// <exception cref="ShardingCoreInvalidOperationException"></exception>
void CheckVirtualDataSource();
/// <summary>
/// 如何根据connectionString 配置 DbContextOptionsBuilder
/// </summary>
/// <param name="connectionString"></param>
/// <param name="dbContextOptionsBuilder"></param>
/// <returns></returns>
DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, DbContextOptionsBuilder dbContextOptionsBuilder);
/// <summary>
/// 如何根据dbConnection 配置DbContextOptionsBuilder
/// </summary>
/// <param name="dbConnection"></param>
/// <param name="dbContextOptionsBuilder"></param>
/// <returns></returns>
DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder);
IDictionary<string, string> GetDataSources();
}
/// <summary>
/// 虚拟数据源 连接所有的实际数据源
@ -99,5 +113,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
public interface IVirtualDataSource<TShardingDbContext> : IVirtualDataSource
where TShardingDbContext : DbContext, IShardingDbContext
{
IVirtualDataSourceRoute<TEntity> GetRoute<TEntity>() where TEntity:class;
}
}

View File

@ -1,35 +0,0 @@
//using System;
//using System.Collections.Generic;
//using Microsoft.EntityFrameworkCore;
//using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
//using ShardingCore.Core.VirtualRoutes;
//using ShardingCore.Sharding.Abstractions;
//namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
//{
// /*
// * @Author: xjm
// * @Description:
// * @Date: Saturday, 06 February 2021 14:24:01
// * @Email: 326308290@qq.com
// */
// public interface IVirtualDataSourceManager
// {
// /// <summary>
// /// 添加链接
// /// </summary>
// /// <param name="physicDataSource"></param>
// bool AddPhysicDataSource(IPhysicDataSource physicDataSource);
// IVirtualDataSource GetVirtualDataSource();
// IPhysicDataSource GetDefaultDataSource();
// string GetDefaultDataSourceName();
// IPhysicDataSource GetPhysicDataSource(string dataSourceName);
// }
// public interface IVirtualDataSourceManager<TShardingDbContext> : IVirtualDataSourceManager where TShardingDbContext : DbContext, IShardingDbContext
// {
// }
//}

View File

@ -30,5 +30,10 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
return _physicDataSources.Keys.ToList();
}
public IDictionary<string, string> GetDataSources()
{
return _physicDataSources.ToDictionary(k => k.Key, k => k.Value.ConnectionString);
}
}
}

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
public class SimpleVirtualDataSourceConfigurationParams<TShardingDbContext>: AbstractVirtualDataSourceConfigurationParams<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly ShardingGlobalConfigOptions _options;
public override string ConfigId { get; }
public override int Priority { get; }
public override int MaxQueryConnectionsLimit { get; }
public override ConnectionModeEnum ConnectionMode { get; }
public override string DefaultDataSourceName { get; }
public override string DefaultConnectionString { get; }
public override IDictionary<string, string> ExtraDataSources { get; }
public override IDictionary<string, IEnumerable<string>> ReadWriteSeparationConfigs { get; }
public override ReadStrategyEnum? ReadStrategy { get; }
public override bool? ReadWriteDefaultEnable { get; }
public override int? ReadWriteDefaultPriority { get; }
public override ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; }
public override IShardingComparer ShardingComparer { get; }
public SimpleVirtualDataSourceConfigurationParams(IServiceProvider serviceProvider,ShardingGlobalConfigOptions options)
{
_options = options;
ConfigId = options.ConfigId;
Priority = options.Priority;
MaxQueryConnectionsLimit = options.MaxQueryConnectionsLimit;
ConnectionMode = options.ConnectionMode;
DefaultDataSourceName = options.DefaultDataSourceName;
DefaultConnectionString = options.DefaultConnectionString;
ExtraDataSources = options.DataSourcesConfigure?.Invoke(serviceProvider)??new ConcurrentDictionary<string, string>();
ShardingComparer = options.ReplaceShardingComparerFactory?.Invoke(serviceProvider) ??
new CSharpLanguageShardingComparer();
if (options.ShardingReadWriteSeparationOptions != null)
{
ReadWriteSeparationConfigs = options.ShardingReadWriteSeparationOptions.ReadWriteSeparationConfigure?.Invoke(serviceProvider);
ReadStrategy = options.ShardingReadWriteSeparationOptions.ReadStrategy;
ReadWriteDefaultEnable = options.ShardingReadWriteSeparationOptions.DefaultEnable;
ReadWriteDefaultPriority = options.ShardingReadWriteSeparationOptions.DefaultPriority;
ReadConnStringGetStrategy = options.ShardingReadWriteSeparationOptions.ReadConnStringGetStrategy;
}
}
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
DbContextOptionsBuilder dbContextOptionsBuilder)
{
_options.ConnectionStringConfigure.Invoke(connectionString, dbContextOptionsBuilder);
return dbContextOptionsBuilder;
}
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection,
DbContextOptionsBuilder dbContextOptionsBuilder)
{
_options.ConnectionConfigure.Invoke(dbConnection, dbContextOptionsBuilder);
return dbContextOptionsBuilder;
}
}
}

View File

@ -1,10 +1,12 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.ShardingEnumerableQueries;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
@ -13,7 +15,9 @@ using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Utils;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
@ -26,26 +30,80 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
*/
public class VirtualDataSource<TShardingDbContext> : IVirtualDataSource<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
public IVirtualDataSourceConfigurationParams ConfigurationParams { get; }
public IConnectionStringManager ConnectionStringManager { get; }
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private readonly ConcurrentDictionary<Type, IVirtualDataSourceRoute> _dataSourceVirtualRoutes = new ConcurrentDictionary<Type, IVirtualDataSourceRoute>();
private readonly IVirtualDataSourceRouteManager<TShardingDbContext> _dataSourceRouteManager;
private readonly IPhysicDataSourcePool _physicDataSourcePool;
public string ConfigId => ConfigurationParams.ConfigId;
public int Priority => ConfigurationParams.Priority;
public string DefaultDataSourceName { get; private set; }
public string DefaultConnectionString { get; private set; }
public bool UseReadWriteSeparation { get; }
public VirtualDataSource(IEntityMetadataManager<TShardingDbContext> entityMetadataManager)
public VirtualDataSource(IEntityMetadataManager<TShardingDbContext> entityMetadataManager, IVirtualDataSourceRouteManager<TShardingDbContext> dataSourceRouteManager, IVirtualDataSourceConfigurationParams<TShardingDbContext> configurationParams)
{
_entityMetadataManager = entityMetadataManager;
ConfigurationParams = configurationParams;
_physicDataSourcePool = new PhysicDataSourcePool();
//Ìí¼ÓÊý¾ÝÔ´
AddPhysicDataSource(new DefaultPhysicDataSource(ConfigurationParams.DefaultDataSourceName, ConfigurationParams.DefaultConnectionString, true));
foreach (var extraDataSource in ConfigurationParams.ExtraDataSources)
{
AddPhysicDataSource(new DefaultPhysicDataSource(extraDataSource.Key, extraDataSource.Value, false));
}
_entityMetadataManager = entityMetadataManager;
_dataSourceRouteManager = dataSourceRouteManager;
UseReadWriteSeparation = ConfigurationParams.UseReadWriteSeparation();
if (UseReadWriteSeparation)
{
CheckReadWriteSeparation();
ConnectionStringManager = new ReadWriteConnectionStringManager(this);
}
else
{
ConnectionStringManager = new DefaultConnectionStringManager(this);
}
}
private void CheckReadWriteSeparation()
{
if (!ConfigurationParams.ReadStrategy.HasValue)
{
throw new ArgumentException(nameof(ConfigurationParams.ReadStrategy));
}
if (!ConfigurationParams.ReadConnStringGetStrategy.HasValue)
{
throw new ArgumentException(nameof(ConfigurationParams.ReadConnStringGetStrategy));
}
if (!ConfigurationParams.ReadWriteDefaultEnable.HasValue)
{
throw new ArgumentException(nameof(ConfigurationParams.ReadWriteDefaultEnable));
}
if (!ConfigurationParams.ReadWriteDefaultPriority.HasValue)
{
throw new ArgumentException(nameof(ConfigurationParams.ReadWriteDefaultPriority));
}
}
public List<string> RouteTo(Type entityType,ShardingDataSourceRouteConfig routeRouteConfig)
public IVirtualDataSourceRoute GetRoute(Type entityType)
{
return _dataSourceRouteManager.GetRoute(entityType);
}
public IVirtualDataSourceRoute<TEntity> GetRoute<TEntity>() where TEntity : class
{
return _dataSourceRouteManager.GetRoute<TEntity>();
}
public List<string> RouteTo(Type entityType, ShardingDataSourceRouteConfig routeRouteConfig)
{
if (!_entityMetadataManager.IsShardingDataSource(entityType))
return new List<string>(1) { DefaultDataSourceName };
var virtualDataSourceRoute = GetRoute( entityType);
var virtualDataSourceRoute = _dataSourceRouteManager.GetRoute(entityType);
if (routeRouteConfig.UseQueryable())
return virtualDataSourceRoute.RouteWithPredicate(routeRouteConfig.GetQueryable(), true);
@ -72,17 +130,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
throw new NotImplementedException(nameof(ShardingDataSourceRouteConfig));
}
public IVirtualDataSourceRoute GetRoute(Type entityType)
{
if(!_entityMetadataManager.IsShardingDataSource(entityType))
throw new ShardingCoreInvalidOperationException(
$"entity type :[{entityType.FullName}] not configure sharding data source");
if (!_dataSourceVirtualRoutes.TryGetValue(entityType, out var dataSourceVirtualRoute))
throw new ShardingCoreInvalidOperationException(
$"entity type :[{entityType.FullName}] not found virtual data source route");
return dataSourceVirtualRoute;
}
/// <summary>
/// 获取默认的数据源信息
/// </summary>
@ -101,7 +148,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
Check.NotNull(dataSourceName, "data source name is null,plz confirm IShardingBootstrapper.Star()");
var dataSource = _physicDataSourcePool.TryGet(dataSourceName);
if (null== dataSource)
if (null == dataSource)
throw new ShardingCoreNotFoundException($"data source:[{dataSourceName}]");
return dataSource;
@ -127,6 +174,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
return DefaultConnectionString;
return GetPhysicDataSource(dataSourceName).ConnectionString;
}
/// <summary>
/// 添加数据源
/// </summary>
@ -148,19 +196,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
return _physicDataSourcePool.TryAdd(physicDataSource);
}
/// <summary>
/// 添加分库路由
/// </summary>
/// <param name="virtualDataSourceRoute"></param>
/// <returns></returns>
/// <exception cref="ShardingCoreInvalidOperationException">对象未配置分库</exception>
public bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute)
{
if (!virtualDataSourceRoute.EntityMetadata.IsShardingDataSource())
throw new ShardingCoreInvalidOperationException($"{virtualDataSourceRoute.EntityMetadata.EntityType.FullName} should configure sharding data source");
return _dataSourceVirtualRoutes.TryAdd(virtualDataSourceRoute.EntityMetadata.EntityType, virtualDataSourceRoute);
}
/// <summary>
/// 是否是默认数据源
/// </summary>
/// <param name="dataSourceName"></param>
@ -182,5 +217,26 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
throw new ShardingCoreInvalidOperationException(
$"virtual data source not inited {nameof(DefaultConnectionString)} in IShardingDbContext null");
}
public DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
DbContextOptionsBuilder dbContextOptionsBuilder)
{
var doUseDbContextOptionsBuilder = ConfigurationParams.UseDbContextOptionsBuilder(connectionString, dbContextOptionsBuilder);
doUseDbContextOptionsBuilder.UseInnerDbContextSharding<TShardingDbContext>();
return doUseDbContextOptionsBuilder;
}
public DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection,
DbContextOptionsBuilder dbContextOptionsBuilder)
{
var doUseDbContextOptionsBuilder = ConfigurationParams.UseDbContextOptionsBuilder(dbConnection, dbContextOptionsBuilder);
doUseDbContextOptionsBuilder.UseInnerDbContextSharding<TShardingDbContext>();
return doUseDbContextOptionsBuilder;
}
public IDictionary<string, string> GetDataSources()
{
return _physicDataSourcePool.GetDataSources();
}
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
public class VirtualDataSourceAccessor: IVirtualDataSourceAccessor
{
private static AsyncLocal<VirtualDataSourceContext> _shardingConfigurationContext = new AsyncLocal<VirtualDataSourceContext>();
/// <summary>
/// sharding route context use in using code block
/// </summary>
public VirtualDataSourceContext DataSourceContext
{
get => _shardingConfigurationContext.Value;
set => _shardingConfigurationContext.Value = value;
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
public class VirtualDataSourceContext
{
public string ConfigId { get; }
public VirtualDataSourceContext(string configId)
{
ConfigId = configId;
}
}
}

View File

@ -1,74 +1,140 @@
//using System;
//using System.Collections.Concurrent;
//using System.Collections.Generic;
//using System.Linq;
//using Microsoft.EntityFrameworkCore;
//using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
//using ShardingCore.Core.VirtualRoutes;
//using ShardingCore.Sharding.Abstractions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Common;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
//namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
//{
// /*
// * @Author: xjm
// * @Description:
// * @Date: Saturday, 06 February 2021 15:24:08
// * @Email: 326308290@qq.com
// */
// public class VirtualDataSourceManager<TShardingDbContext> : IVirtualDataSourceManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
// {
// private readonly IServiceProvider _serviceProvider;
// /// <summary>
// /// {sharding db context type :{entity type:virtual data source}}
// /// </summary>
// private readonly ConcurrentDictionary<Type, IVirtualDataSource> _virtualDataSources = new ConcurrentDictionary<Type, IVirtualDataSource>();
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
public class VirtualDataSourceManager<TShardingDbContext> : IVirtualDataSourceManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly IShardingConfigurationOptions<TShardingDbContext> _options;
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private readonly IVirtualDataSourceRouteManager<TShardingDbContext> _virtualDataSourceRouteManager;
private readonly IVirtualDataSourceAccessor _virtualDataSourceAccessor;
private readonly ConcurrentDictionary<string, IVirtualDataSource> _virtualDataSources = new();
private string _defaultConfigId;
private IVirtualDataSource _defaultVirtualDataSource;
public VirtualDataSourceManager(IServiceProvider serviceProvider,IShardingConfigurationOptions<TShardingDbContext> options,IEntityMetadataManager<TShardingDbContext> entityMetadataManager,IVirtualDataSourceRouteManager<TShardingDbContext> virtualDataSourceRouteManager, IVirtualDataSourceAccessor virtualDataSourceAccessor)
{
// public VirtualDataSourceManager(IServiceProvider serviceProvider)
// {
// _serviceProvider = serviceProvider;
// //var shardingEntities = AssemblyHelper.CurrentDomain.GetAssemblies().SelectMany(o => o.GetTypes())
// // .Where(type => !String.IsNullOrEmpty(type.Namespace))
// // .Where(type => !type.IsAbstract&&type.GetInterfaces()
// // .Any(it => it.IsInterface &&typeof(IShardingDataSource)==it)
// // );
// //foreach (var shardingEntity in shardingEntities)
// //{
// // Type genericType = typeof(IVirtualDataSource<>);
// // Type interfaceType = genericType.MakeGenericType(shardingEntity);
// // var virtualDataSource = (IVirtualDataSource)serviceProvider.GetService(interfaceType);
// // _virtualDataSources.TryAdd(virtualDataSource.EntityType, virtualDataSource);
// //}
// }
_options = options;
_entityMetadataManager = entityMetadataManager;
_virtualDataSourceRouteManager = virtualDataSourceRouteManager;
var allShardingGlobalConfigOptions = options.GetAllShardingGlobalConfigOptions();
if (allShardingGlobalConfigOptions.IsEmpty())
throw new ArgumentException($"sharding virtual data source is empty");
_virtualDataSourceAccessor = virtualDataSourceAccessor;
if (options is ShardingMultiConfigurationOptions<TShardingDbContext> shardingMultiConfigurationOptions)
{
IsMultiShardingConfiguration = true;
ShardingConfigurationStrategy = shardingMultiConfigurationOptions.ShardingConfigurationStrategy;
}
else if (options is ShardingSingleConfigurationOptions<TShardingDbContext> shardingSingleConfigurationOptions)
{
IsMultiShardingConfiguration = false;
ShardingConfigurationStrategy = shardingSingleConfigurationOptions.ShardingConfigurationStrategy;
}
foreach (var shardingGlobalConfigOption in allShardingGlobalConfigOptions)
{
var simpleVirtualDataSourceConfigurationParams = new SimpleVirtualDataSourceConfigurationParams<TShardingDbContext>(serviceProvider,shardingGlobalConfigOption);
var dataSource = new VirtualDataSource<TShardingDbContext>(_entityMetadataManager,_virtualDataSourceRouteManager, simpleVirtualDataSourceConfigurationParams);
dataSource.CheckVirtualDataSource();
if (!IsMultiShardingConfiguration)
{
if (_defaultVirtualDataSource != null || _defaultConfigId != null)
throw new ShardingCoreInvalidOperationException("set sharding configuration error");
_defaultVirtualDataSource = dataSource;
_defaultConfigId = dataSource.ConfigId;
}
_virtualDataSources.TryAdd(dataSource.ConfigId, dataSource);
}
// public bool AddPhysicDataSource(IPhysicDataSource physicDataSource)
// {
// throw new NotImplementedException();
// }
if (IsMultiShardingConfiguration)
{
var maxShardingConfiguration = _virtualDataSources.Values.OrderByDescending(o => o.Priority).FirstOrDefault();
_defaultVirtualDataSource = maxShardingConfiguration;
_defaultConfigId = maxShardingConfiguration.ConfigId;
}
}
public bool IsMultiShardingConfiguration { get; }
public ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; }
public IVirtualDataSource GetVirtualDataSource()
{
if (!IsMultiShardingConfiguration)
return _defaultVirtualDataSource;
var configId = _virtualDataSourceAccessor.DataSourceContext?.ConfigId;
if (!string.IsNullOrWhiteSpace(configId))
{
var hasValue = _virtualDataSources.TryGetValue(configId, out var virtualDataSource);
if (hasValue)
{
return virtualDataSource;
}
}
// public IVirtualDataSource GetVirtualDataSource()
// {
// if (!_virtualDataSources.TryGetValue(shardingDbContextType, out var virtualDataSource))
// throw new ShardingCoreInvalidOperationException($"not found virtual data source sharding db context type:[{shardingDbContextType.FullName}]");
// return virtualDataSource;
// }
switch (ShardingConfigurationStrategy)
{
case ShardingConfigurationStrategyEnum.ReturnNull: return null;
case ShardingConfigurationStrategyEnum.ReturnHighPriority: return _defaultVirtualDataSource;
case ShardingConfigurationStrategyEnum.ThrowIfNull: throw new ShardingCoreNotFoundException($"no configuration,config id:[{configId}]");
default:
throw new ShardingCoreException(
$"unknown {nameof(ShardingConfigurationStrategyEnum)}:[{ShardingConfigurationStrategy}]");
}
}
// public IPhysicDataSource GetDefaultDataSource()
// {
// var virtualDataSource = GetVirtualDataSource(shardingDbContextType);
// return virtualDataSource.GetDefaultDataSource();
// }
List<IVirtualDataSource<TShardingDbContext>> IVirtualDataSourceManager<TShardingDbContext>.GetAllVirtualDataSources()
{
return GetAllVirtualDataSources().Select(o => (IVirtualDataSource<TShardingDbContext>)o).ToList();
}
// public string GetDefaultDataSourceName()
// {
// var virtualDataSource = GetVirtualDataSource(shardingDbContextType);
// return virtualDataSource.DefaultDataSourceName;
// }
public void AddVirtualDataSource(IVirtualDataSourceConfigurationParams<TShardingDbContext> configurationParams)
{
if (!IsMultiShardingConfiguration)
throw new NotSupportedException("not support multi sharding configuration");
var dataSource = new VirtualDataSource<TShardingDbContext>(_entityMetadataManager, _virtualDataSourceRouteManager, configurationParams);
dataSource.CheckVirtualDataSource();
if(_virtualDataSources.TryAdd(dataSource.ConfigId, dataSource))
{
if (IsMultiShardingConfiguration)
{
var maxShardingConfiguration = _virtualDataSources.Values.OrderByDescending(o => o.Priority).FirstOrDefault();
_defaultVirtualDataSource = maxShardingConfiguration;
_defaultConfigId = maxShardingConfiguration.ConfigId;
}
}
}
// public IPhysicDataSource GetPhysicDataSource(string dataSourceName)
// {
// throw new NotImplementedException();
// }
// }
//}
IVirtualDataSource<TShardingDbContext> IVirtualDataSourceManager<TShardingDbContext>.GetVirtualDataSource()
{
return (IVirtualDataSource<TShardingDbContext>)GetVirtualDataSource();
}
public List<IVirtualDataSource> GetAllVirtualDataSources()
{
if (!IsMultiShardingConfiguration)
return new List<IVirtualDataSource>(1) { _defaultVirtualDataSource };
return _virtualDataSources.Values.ToList();
}
public VirtualDataSourceScope CreateScope(string configId)
{
var virtualDataSourceScope = new VirtualDataSourceScope(_virtualDataSourceAccessor);
_virtualDataSourceAccessor.DataSourceContext = new VirtualDataSourceContext(configId);
return virtualDataSourceScope;
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingEnumerableQueries;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
public class VirtualDataSourceRouteManager<TShardingDbContext> : IVirtualDataSourceRouteManager<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private readonly ConcurrentDictionary<Type, IVirtualDataSourceRoute> _dataSourceVirtualRoutes = new ConcurrentDictionary<Type, IVirtualDataSourceRoute>();
public VirtualDataSourceRouteManager(IEntityMetadataManager<TShardingDbContext> entityMetadataManager)
{
_entityMetadataManager = entityMetadataManager;
}
public IVirtualDataSourceRoute<TEntity> GetRoute<TEntity>() where TEntity : class
{
return (IVirtualDataSourceRoute<TEntity>)GetRoute(typeof(TEntity));
}
public IVirtualDataSourceRoute GetRoute(Type entityType)
{
if (!_entityMetadataManager.IsShardingDataSource(entityType))
throw new ShardingCoreInvalidOperationException(
$"entity type :[{entityType.FullName}] not configure sharding data source");
if (!_dataSourceVirtualRoutes.TryGetValue(entityType, out var dataSourceVirtualRoute))
throw new ShardingCoreInvalidOperationException(
$"entity type :[{entityType.FullName}] not found virtual data source route");
return dataSourceVirtualRoute;
}
/// <summary>
/// 添加分库路由
/// </summary>
/// <param name="virtualDataSourceRoute"></param>
/// <returns></returns>
/// <exception cref="ShardingCoreInvalidOperationException">对象未配置分库</exception>
public bool AddVirtualDataSourceRoute(IVirtualDataSourceRoute virtualDataSourceRoute)
{
if (!virtualDataSourceRoute.EntityMetadata.IsShardingDataSource())
throw new ShardingCoreInvalidOperationException($"{virtualDataSourceRoute.EntityMetadata.EntityType.FullName} should configure sharding data source");
return _dataSourceVirtualRoutes.TryAdd(virtualDataSourceRoute.EntityMetadata.EntityType, virtualDataSourceRoute);
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
public class VirtualDataSourceScope:IDisposable
{
/// <summary>
/// 分片配置访问器
/// </summary>
public IVirtualDataSourceAccessor VirtualDataSourceAccessor { get; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="virtualDataSourceAccessor"></param>
public VirtualDataSourceScope(IVirtualDataSourceAccessor virtualDataSourceAccessor)
{
VirtualDataSourceAccessor = virtualDataSourceAccessor;
}
/// <summary>
/// 回收
/// </summary>
public void Dispose()
{
VirtualDataSourceAccessor.DataSourceContext = null;
}
}
}

View File

@ -35,7 +35,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
{
if (EnableRouteParseCompileCache.HasValue)
return EnableRouteParseCompileCache.Value;
return ShardingConfigOption.EnableDataSourceRouteCompileCache.GetValueOrDefault();
return EntityConfigOptions.EnableDataSourceRouteCompileCache.GetValueOrDefault();
}
/// <summary>

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.EntityShardingMetadatas;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.MergeEngines.ParallelControl;
using ShardingCore.Sharding.PaginationConfigurations;
@ -19,7 +20,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
{
public EntityMetadata EntityMetadata { get; private set; }
private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce();
public IShardingConfigOption ShardingConfigOption { get; private set; }
public IShardingEntityConfigOptions EntityConfigOptions { get; private set; }
public void Initialize(EntityMetadata entityMetadata)
@ -35,8 +36,8 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
paginationConfiguration.Configure(paginationBuilder);
}
ShardingConfigOption =
ShardingContainer.GetRequiredShardingConfigOption(entityMetadata.ShardingDbContextType);
EntityConfigOptions =
ShardingContainer.GetRequiredShardingEntityConfigOption(entityMetadata.ShardingDbContextType);
}
public virtual IPaginationConfiguration<T> CreatePaginationConfiguration()

View File

@ -2,7 +2,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
{
@ -19,15 +21,20 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
/// <typeparam name="T"></typeparam>
public class DataSourceRouteRuleContext
{
public ISet<Type> QueryEntities { get; }
public DataSourceRouteRuleContext(IQueryable queryable,Type dbContextType)
public DataSourceRouteRuleContext(IQueryable queryable,IShardingDbContext shardingDbContext)
{
Queryable = queryable;
QueryEntities = queryable.ParseQueryableEntities(dbContextType);
ShardingDbContext = shardingDbContext;
VirtualDataSource = shardingDbContext.GetVirtualDataSource();
QueryEntities = queryable.ParseQueryableEntities(shardingDbContext.GetType());
}
public ISet<Type> QueryEntities { get; }
/// <summary>
/// 查询条件
/// </summary>
public IQueryable Queryable { get; }
public IShardingDbContext ShardingDbContext { get; }
public IVirtualDataSource VirtualDataSource { get; }
}
}

View File

@ -21,21 +21,20 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
*/
public class DataSourceRouteRuleEngine<TShardingDbContext> : IDataSourceRouteRuleEngine<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
public DataSourceRouteRuleEngine(IVirtualDataSource<TShardingDbContext> virtualDataSource,IEntityMetadataManager<TShardingDbContext> entityMetadataManager)
public DataSourceRouteRuleEngine(IEntityMetadataManager<TShardingDbContext> entityMetadataManager)
{
_virtualDataSource = virtualDataSource;
_entityMetadataManager = entityMetadataManager;
}
public DataSourceRouteResult Route(DataSourceRouteRuleContext routeRuleContext)
{
var virtualDataSource = routeRuleContext.VirtualDataSource;
var dataSourceMaps = new Dictionary<Type, ISet<string>>();
var notShardingDataSourceEntityType = routeRuleContext.QueryEntities.FirstOrDefault(o => !_entityMetadataManager.IsShardingDataSource(o));
//存在不分库的
if (notShardingDataSourceEntityType != null)
dataSourceMaps.Add(notShardingDataSourceEntityType, new HashSet<string>() { _virtualDataSource.DefaultDataSourceName });
dataSourceMaps.Add(notShardingDataSourceEntityType, new HashSet<string>() { virtualDataSource.DefaultDataSourceName });
//if (queryEntities.Count > 1)
@ -46,7 +45,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
{
continue;
}
var dataSourceConfigs = _virtualDataSource.RouteTo(queryEntity,new ShardingDataSourceRouteConfig(routeRuleContext.Queryable));
var dataSourceConfigs = virtualDataSource.RouteTo(queryEntity,new ShardingDataSourceRouteConfig(routeRuleContext.Queryable));
if (!dataSourceMaps.ContainsKey(queryEntity))
{
dataSourceMaps.Add(queryEntity, dataSourceConfigs.ToHashSet());

View File

@ -33,20 +33,22 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="queryable"></param>
/// <param name="shardingDbContext"></param>
/// <returns></returns>
public DataSourceRouteRuleContext CreateContext(IQueryable queryable)
public DataSourceRouteRuleContext CreateContext(IQueryable queryable,IShardingDbContext shardingDbContext)
{
return new DataSourceRouteRuleContext(queryable,typeof(TShardingDbContext));
return new DataSourceRouteRuleContext(queryable, shardingDbContext);
}
/// <summary>
/// 路由到具体的物理数据源
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="queryable"></param>
/// <param name="shardingDbContext"></param>
/// <returns></returns>
public DataSourceRouteResult Route(IQueryable queryable)
public DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext)
{
var ruleContext = CreateContext(queryable);
var ruleContext = CreateContext(queryable, shardingDbContext);
return _dataSourceRouteRuleEngine.Route(ruleContext);
}
/// <summary>

View File

@ -16,8 +16,8 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
*/
public interface IDataSourceRouteRuleEngineFactory
{
DataSourceRouteRuleContext CreateContext(IQueryable queryable);
DataSourceRouteResult Route(IQueryable queryable);
DataSourceRouteRuleContext CreateContext(IQueryable queryable, IShardingDbContext shardingDbContext);
DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext);
DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext);
}
public interface IDataSourceRouteRuleEngineFactory<TShardingDbContext> : IDataSourceRouteRuleEngineFactory

View File

@ -37,7 +37,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
if (EnableRouteParseCompileCache.HasValue)
return EnableRouteParseCompileCache.Value;
return ShardingConfigOption.EnableTableRouteCompileCache.GetValueOrDefault();
return EntityConfigOptions.EnableTableRouteCompileCache.GetValueOrDefault();
}
/// <summary>
/// 对表达式进行缓存编译默认永久缓存单个参数表达式且不包含orElse只包含单个AndAlso或者没有AndAlso的,

View File

@ -5,6 +5,7 @@ using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.MergeEngines.ParallelControl;
@ -22,14 +23,15 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce();
public IShardingConfigOption ShardingConfigOption { get; private set; }
public IShardingEntityConfigOptions EntityConfigOptions { get; private set; }
public virtual void Initialize(EntityMetadata entityMetadata)
{
if (!_doOnlyOnce.IsUnDo())
throw new ShardingCoreInvalidOperationException("already init");
EntityMetadata = entityMetadata;
ShardingConfigOption =
ShardingContainer.GetRequiredShardingConfigOption(entityMetadata.ShardingDbContextType);
EntityConfigOptions =
ShardingContainer.GetRequiredShardingEntityConfigOption(entityMetadata.ShardingDbContextType);
}
public virtual IPaginationConfiguration<T> CreatePaginationConfiguration()
{

View File

@ -30,6 +30,8 @@ using ShardingCore.Sharding.ShardingQueryExecutors;
using ShardingCore.TableCreator;
using System;
using ShardingCore.Core.QueryTrackers;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.DynamicDataSources;
using ShardingCore.Sharding.ParallelTables;
using ShardingCore.Sharding.ReadWriteConfigurations;
@ -53,13 +55,11 @@ namespace ShardingCore
/// </summary>
/// <typeparam name="TShardingDbContext"></typeparam>
/// <param name="services"></param>
/// <param name="optionsAction"></param>
/// <param name="contextLifetime"></param>
/// <param name="optionsLifetime"></param>
/// <returns></returns>
/// <exception cref="NotSupportedException"></exception>
public static ShardingCoreConfigBuilder<TShardingDbContext> AddShardingDbContext<TShardingDbContext>(this IServiceCollection services,
Action<string, DbContextOptionsBuilder> optionsAction = null,
ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
ServiceLifetime optionsLifetime = ServiceLifetime.Scoped)
where TShardingDbContext : DbContext, IShardingDbContext
@ -70,20 +70,20 @@ namespace ShardingCore
throw new NotSupportedException($"{nameof(optionsLifetime)}:{nameof(ServiceLifetime.Singleton)}");
Action<IServiceProvider, DbContextOptionsBuilder> shardingOptionAction = (sp, option) =>
{
var virtualDataSource = sp.GetRequiredService<IVirtualDataSource<TShardingDbContext>>();
var virtualDataSource = sp.GetRequiredService<IVirtualDataSourceManager<TShardingDbContext>>().GetVirtualDataSource();
var connectionString = virtualDataSource.GetConnectionString(virtualDataSource.DefaultDataSourceName);
optionsAction?.Invoke(connectionString, option);
virtualDataSource.ConfigurationParams.UseDbContextOptionsBuilder(connectionString, option);
option.UseSharding<TShardingDbContext>();
};
services.AddDbContext<TShardingDbContext>(shardingOptionAction, contextLifetime, optionsLifetime);
return services.AddShardingConfigure<TShardingDbContext>(optionsAction);
return services.AddShardingConfigure<TShardingDbContext>();
}
public static ShardingCoreConfigBuilder<TShardingDbContext> AddShardingConfigure<TShardingDbContext>(this IServiceCollection services, Action<string, DbContextOptionsBuilder> queryConfigure)
public static ShardingCoreConfigBuilder<TShardingDbContext> AddShardingConfigure<TShardingDbContext>(this IServiceCollection services)
where TShardingDbContext : DbContext, IShardingDbContext
{
ShardingCoreHelper.CheckContextConstructors<TShardingDbContext>();
return new ShardingCoreConfigBuilder<TShardingDbContext>(services, queryConfigure);
return new ShardingCoreConfigBuilder<TShardingDbContext>(services);
}
internal static IServiceCollection AddInternalShardingCore(this IServiceCollection services)
@ -98,10 +98,11 @@ namespace ShardingCore
services.TryAddSingleton(typeof(IStreamMergeContextFactory<>), typeof(StreamMergeContextFactory<>));
services.TryAddSingleton(typeof(IShardingTableCreator<>), typeof(ShardingTableCreator<>));
//虚拟数据源管理
services.TryAddSingleton(typeof(IVirtualDataSource<>), typeof(VirtualDataSource<>));
services.TryAddSingleton(typeof(IVirtualDataSourceRouteManager<>), typeof(VirtualDataSourceRouteManager<>));
services.TryAddSingleton(typeof(IDataSourceRouteRuleEngine<>), typeof(DataSourceRouteRuleEngine<>));
services.TryAddSingleton(typeof(IDataSourceRouteRuleEngineFactory<>), typeof(DataSourceRouteRuleEngineFactory<>));
//读写分离链接创建工厂
services.TryAddSingleton<IReadWriteConnectorFactory, ReadWriteConnectorFactory>();
//虚拟表管理
services.TryAddSingleton(typeof(IVirtualTableManager<>), typeof(VirtualTableManager<>));
@ -163,5 +164,29 @@ namespace ShardingCore
.ReplaceService<IModelSource,ShardingModelSource>()
.ReplaceService<IModelCustomizer, ShardingModelCustomizer<TShardingDbContext>>();
}
//public static IServiceCollection AddSingleShardingDbContext<TShardingDbContext>(this IServiceCollection services, Action<ShardingGlobalConfigOptions> configure,
// Action<string, DbContextOptionsBuilder> optionsAction = null,
// ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
// ServiceLifetime optionsLifetime = ServiceLifetime.Scoped)
// where TShardingDbContext : DbContext, IShardingDbContext
//{
// if (contextLifetime == ServiceLifetime.Singleton)
// throw new NotSupportedException($"{nameof(contextLifetime)}:{nameof(ServiceLifetime.Singleton)}");
// if (optionsLifetime == ServiceLifetime.Singleton)
// throw new NotSupportedException($"{nameof(optionsLifetime)}:{nameof(ServiceLifetime.Singleton)}");
// Action<IServiceProvider, DbContextOptionsBuilder> shardingOptionAction = (sp, option) =>
// {
// var virtualDataSource = sp.GetRequiredService<IVirtualDataSourceManager<TShardingDbContext>>().GetVirtualDataSource();
// var connectionString = virtualDataSource.GetConnectionString(virtualDataSource.DefaultDataSourceName);
// optionsAction?.Invoke(connectionString, option);
// option.UseSharding<TShardingDbContext>();
// };
// services.AddDbContext<TShardingDbContext>(shardingOptionAction, contextLifetime, optionsLifetime);
// return services.AddShardingConfigure<TShardingDbContext>(optionsAction);
//}
}
}

View File

@ -4,6 +4,9 @@ using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ShardingCore.Core;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.ShardingConfigurations.ConfigBuilders;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
@ -24,17 +27,19 @@ namespace ShardingCore.DIExtensions
public ShardingConfigOption<TShardingDbContext> ShardingConfigOption { get; }
public List<ShardingGlobalConfigOptions> ShardingGlobalConfigOptions { get; }
public ShardingEntityConfigOptions<TShardingDbContext> ShardingEntityConfigOptions { get; }
public ShardingCoreConfigBuilder(IServiceCollection services,Action<string,DbContextOptionsBuilder> queryConfigure)
public ShardingCoreConfigBuilder(IServiceCollection services)
{
Services = services;
ShardingConfigOption = new ShardingConfigOption<TShardingDbContext>();
ShardingConfigOption.UseShardingQuery(queryConfigure);
ShardingGlobalConfigOptions = new List<ShardingGlobalConfigOptions>();
ShardingEntityConfigOptions = new ShardingEntityConfigOptions<TShardingDbContext>();
}
[Obsolete("plz use AddEntityConfig")]
public ShardingTransactionBuilder<TShardingDbContext> Begin(Action<ShardingCoreBeginOptions> shardingCoreBeginOptionsConfigure)
{
var shardingCoreBeginOptions = new ShardingCoreBeginOptions();
@ -64,6 +69,12 @@ namespace ShardingCore.DIExtensions
return new ShardingTransactionBuilder<TShardingDbContext>(this);
//return new ShardingQueryBuilder<TShardingDbContext>(this);
}
public ShardingEntityConfigBuilder<TShardingDbContext> AddEntityConfig(Action<ShardingEntityConfigOptions<TShardingDbContext>> entityConfigure)
{
entityConfigure?.Invoke(ShardingEntityConfigOptions);
return new ShardingEntityConfigBuilder<TShardingDbContext>(this);
}
//public ShardingCoreConfigBuilder<TShardingDbContext, TActualDbContext> AddDefaultDataSource(string dataSourceName, string connectionString)
//{
// if (!string.IsNullOrWhiteSpace(defaultDataSourceName) || !string.IsNullOrWhiteSpace(defaultConnectionString))
@ -84,6 +95,14 @@ namespace ShardingCore.DIExtensions
public class ShardingCoreBeginOptions
{
/// <summary>
/// 配置id
/// </summary>
public string ConfigId { get; set; }
/// <summary>
/// 优先级
/// </summary>
public int Priority { get; set; }
/// <summary>
/// 如果数据库不存在就创建并且创建表除了分表的
/// </summary>
@ -114,7 +133,7 @@ namespace ShardingCore.DIExtensions
public bool? EnableTableRouteCompileCache { get; set; }
public bool? EnableDataSourceRouteCompileCache { get; set; }
private readonly ISet<Type> _createTableEntities = new HashSet<Type>();
private readonly ISet<Type> _createTableEntities = new HashSet<Type>();
public void AddEntitiesTryCreateTable(params Type[] entityTypes)
{

View File

@ -42,7 +42,7 @@ namespace ShardingCore.DIExtensions
/// </summary>
/// <param name="newShardingComparerFactory"></param>
/// <returns></returns>
public ShardingCoreConfigEndBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer<TShardingDbContext>> newShardingComparerFactory)
public ShardingCoreConfigEndBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer> newShardingComparerFactory)
{
_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory);
return this;
@ -64,19 +64,19 @@ namespace ShardingCore.DIExtensions
_shardingCoreConfigBuilder.ShardingConfigOption);
//添加创建TActualDbContext 的DbContextOptionsBuilder创建者
var config = new ShardingDbContextOptionsBuilderConfig<TShardingDbContext>(
_shardingCoreConfigBuilder.ShardingConfigOption.SameConnectionConfigure,
_shardingCoreConfigBuilder.ShardingConfigOption.DefaultQueryConfigure);
services
.AddSingleton<IShardingDbContextOptionsBuilderConfig<TShardingDbContext>,
ShardingDbContextOptionsBuilderConfig<TShardingDbContext>>(sp => config);
////添加创建TActualDbContext 的DbContextOptionsBuilder创建者
//var config = new ShardingDbContextOptionsBuilderConfig<TShardingDbContext>(
// _shardingCoreConfigBuilder.ShardingConfigOption.SameConnectionConfigure,
// _shardingCoreConfigBuilder.ShardingConfigOption.DefaultQueryConfigure);
//services
// .AddSingleton<IShardingDbContextOptionsBuilderConfig<TShardingDbContext>,
// ShardingDbContextOptionsBuilderConfig<TShardingDbContext>>(sp => config);
if (_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparerFactory == null)
{
throw new ShardingCoreConfigException($"{nameof(_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparerFactory)} is null");
}
services.AddSingleton<IShardingComparer<TShardingDbContext>>(_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparerFactory);
//services.AddSingleton<IShardingComparer>(_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparerFactory);
if (_shardingCoreConfigBuilder.ShardingConfigOption.TableEnsureManagerFactory == null)
{
throw new ShardingCoreConfigException($"{nameof(_shardingCoreConfigBuilder.ShardingConfigOption.TableEnsureManagerFactory)} is null");
@ -84,15 +84,15 @@ namespace ShardingCore.DIExtensions
services.AddSingleton<ITableEnsureManager<TShardingDbContext>>(_shardingCoreConfigBuilder.ShardingConfigOption.TableEnsureManagerFactory);
if (!UseReadWrite)
{
services.AddTransient<IConnectionStringManager<TShardingDbContext>, DefaultConnectionStringManager<TShardingDbContext>>();
}
else
{
services.AddTransient<IConnectionStringManager<TShardingDbContext>, ReadWriteConnectionStringManager<TShardingDbContext>>();
RegisterReadWriteConfigure(services);
}
//if (!UseReadWrite)
//{
// services.AddTransient<IConnectionStringManager<TShardingDbContext>, DefaultConnectionStringManager<TShardingDbContext>>();
//}
//else
//{
// services.AddTransient<IConnectionStringManager<TShardingDbContext>, ReadWriteConnectionStringManager<TShardingDbContext>>();
// RegisterReadWriteConfigure(services);
//}
services.AddInternalShardingCore();
return services;
@ -105,27 +105,27 @@ namespace ShardingCore.DIExtensions
/// <exception cref="ShardingCoreInvalidOperationException"></exception>
private void RegisterReadWriteConfigure(IServiceCollection services)
{
services.AddSingleton<IReadWriteOptions<TShardingDbContext>, ReadWriteOptions<TShardingDbContext>>(sp =>
new ReadWriteOptions<TShardingDbContext>(
_shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultPriority,
_shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultEnable,
_shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum,
_shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringGetStrategy));
//services.AddSingleton<IReadWriteOptions<TShardingDbContext>, ReadWriteOptions<TShardingDbContext>>(sp =>
// new ReadWriteOptions<TShardingDbContext>(
// _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultPriority,
// _shardingCoreConfigBuilder.ShardingConfigOption.ReadWriteDefaultEnable,
// _shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum,
// _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringGetStrategy));
services
.AddSingleton<IShardingConnectionStringResolver<TShardingDbContext>,
ReadWriteShardingConnectionStringResolver<TShardingDbContext>>(sp =>
{
var readWriteConnectorFactory = sp.GetRequiredService<IReadWriteConnectorFactory>();
var readConnStrings = _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringConfigure(sp);
var readWriteLoopConnectors = readConnStrings.Select(o => readWriteConnectorFactory.CreateConnector<TShardingDbContext>(_shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum,o.Key,o.Value));
//services
// .AddSingleton<IShardingConnectionStringResolver<TShardingDbContext>,
// ReadWriteShardingConnectionStringResolver<TShardingDbContext>>(sp =>
// {
// var readWriteConnectorFactory = sp.GetRequiredService<IReadWriteConnectorFactory>();
// var readConnStrings = _shardingCoreConfigBuilder.ShardingConfigOption.ReadConnStringConfigure(sp);
// var readWriteLoopConnectors = readConnStrings.Select(o => readWriteConnectorFactory.CreateConnector<TShardingDbContext>(_shardingCoreConfigBuilder.ShardingConfigOption.ReadStrategyEnum,o.Key,o.Value));
return new ReadWriteShardingConnectionStringResolver<TShardingDbContext>(
readWriteLoopConnectors);
});
// return new ReadWriteShardingConnectionStringResolver<TShardingDbContext>(
// readWriteLoopConnectors);
// });
services.TryAddSingleton<IShardingReadWriteManager, ShardingReadWriteManager>();
services.AddSingleton<IShardingReadWriteAccessor, ShardingReadWriteAccessor<TShardingDbContext>>();
services.TryAddSingleton<IShardingReadWriteAccessor, ShardingReadWriteAccessor<TShardingDbContext>>();
}
}

View File

@ -43,7 +43,7 @@ namespace ShardingCore.DIExtensions
}
return new ShardingReadWriteSeparationBuilder<TShardingDbContext>(_shardingCoreConfigBuilder);
}
public ShardingDataBaseOrTableBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer<TShardingDbContext>> newShardingComparerFactory)
public ShardingDataBaseOrTableBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer> newShardingComparerFactory)
{
_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory);
return this;

View File

@ -39,7 +39,7 @@ namespace ShardingCore.DIExtensions
return new ShardingTableBuilder<TShardingDbContext>(_shardingCoreConfigBuilder);
}
public ShardingDataSourceRouteBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer<TShardingDbContext>> newShardingComparerFactory)
public ShardingDataSourceRouteBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer> newShardingComparerFactory)
{
_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory);
return this;

View File

@ -37,7 +37,7 @@ namespace ShardingCore.DIExtensions
_shardingCoreConfigBuilder.ShardingConfigOption.UseReadWriteConfiguration(readWriteSeparationConfigure,readStrategyEnum, defaultEnable,defaultPriority, readConnStringGetStrategy);
return new ShardingCoreConfigEndBuilder<TShardingDbContext>(_shardingCoreConfigBuilder);
}
public ShardingReadWriteSeparationBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer<TShardingDbContext>> newShardingComparerFactory)
public ShardingReadWriteSeparationBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer> newShardingComparerFactory)
{
_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory);
return this;

View File

@ -38,7 +38,7 @@ namespace ShardingCore.DIExtensions
}
return new ShardingReadWriteSeparationBuilder<TShardingDbContext>(_shardingCoreConfigBuilder);
}
public ShardingTableBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer<TShardingDbContext>> newShardingComparerFactory)
public ShardingTableBuilder<TShardingDbContext> ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer> newShardingComparerFactory)
{
_shardingCoreConfigBuilder.ShardingConfigOption.ReplaceShardingComparer(newShardingComparerFactory);
return this;

View File

@ -1,85 +1,76 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ShardingCore.Bootstrapers;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
using ShardingCore.TableCreator;
using ShardingCore.TableExists;
using ShardingCore.TableExists.Abstractions;
using System;
using System.Collections.Generic;
using System.Threading;
namespace ShardingCore.DynamicDataSources
{
public class DataSourceInitializer<TShardingDbContext> : IDataSourceInitializer<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly IShardingEntityConfigOptions<TShardingDbContext> _entityConfigOptions;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IVirtualTableManager<TShardingDbContext> _virtualTableManager;
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private readonly IShardingTableCreator<TShardingDbContext> _tableCreator;
private readonly ILogger<DataSourceInitializer<TShardingDbContext>> _logger;
private readonly IShardingConfigOption<TShardingDbContext> _shardingConfigOption;
public DataSourceInitializer(IShardingConfigOption<TShardingDbContext> shardingConfigOption,
public DataSourceInitializer(
IShardingEntityConfigOptions<TShardingDbContext> entityConfigOptions,
IRouteTailFactory routeTailFactory, IVirtualTableManager<TShardingDbContext> virtualTableManager,
IEntityMetadataManager<TShardingDbContext> entityMetadataManager,
IShardingTableCreator<TShardingDbContext> shardingTableCreator,
IVirtualDataSource<TShardingDbContext> virtualDataSource,
ILogger<DataSourceInitializer<TShardingDbContext>> logger)
{
_shardingConfigOption = shardingConfigOption;
_entityConfigOptions = entityConfigOptions;
_routeTailFactory = routeTailFactory;
_virtualTableManager = virtualTableManager;
_entityMetadataManager = entityMetadataManager;
_tableCreator = shardingTableCreator;
_virtualDataSource = virtualDataSource;
_logger = logger;
}
public void InitConfigure(string dataSourceName, string connectionString, bool isOnStart)
public void InitConfigure(IVirtualDataSource<TShardingDbContext> virtualDataSource, string dataSourceName, string connectionString, bool isOnStart)
{
using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope())
{
_virtualDataSource.AddPhysicDataSource(new DefaultPhysicDataSource(dataSourceName, connectionString, false));
using var context = serviceScope.ServiceProvider.GetService<TShardingDbContext>();
if (_shardingConfigOption.EnsureCreatedWithOutShardingTable||!isOnStart)
EnsureCreated(context, dataSourceName);
var tableEnsureManager = ShardingContainer.GetService<ITableEnsureManager<TShardingDbContext>>();
//获取数据库存在的所有的表
var existTables = tableEnsureManager?.GetExistTables(context, dataSourceName) ?? new HashSet<string>();
if (_entityConfigOptions.EnsureCreatedWithOutShardingTable || !isOnStart)
EnsureCreated(virtualDataSource, context, dataSourceName);
//var tableEnsureManager = ShardingContainer.GetService<ITableEnsureManager<TShardingDbContext>>();
////获取数据库存在的所有的表
//var existTables = tableEnsureManager?.GetExistTables(context, dataSourceName) ?? new HashSet<string>();
var existTables = new HashSet<string>();
foreach (var entity in context.Model.GetEntityTypes())
{
var entityType = entity.ClrType;
if (_virtualDataSource.IsDefault(dataSourceName))
if (virtualDataSource.IsDefault(dataSourceName))
{
if (_entityMetadataManager.IsShardingTable(entityType))
{
var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
//创建表
CreateDataTable(dataSourceName, virtualTable, existTables,isOnStart);
CreateDataTable( dataSourceName, virtualTable, existTables, isOnStart);
}
}
else
{
if (_entityMetadataManager.IsShardingDataSource(entityType))
{
var virtualDataSourceRoute = _virtualDataSource.GetRoute(entityType);
var virtualDataSourceRoute = virtualDataSource.GetRoute(entityType);
if (virtualDataSourceRoute.GetAllDataSourceNames().Contains(dataSourceName))
{
if (_entityMetadataManager.IsShardingTable(entityType))
@ -91,11 +82,6 @@ namespace ShardingCore.DynamicDataSources
}
}
}
if (isOnStart&&_shardingConfigOption.NeedCreateTable(entityType))
{
if (!existTables.Contains(entity.GetEntityTypeTableName()))
_tableCreator.CreateTable(dataSourceName, entityType, string.Empty);
}
}
}
}
@ -117,7 +103,7 @@ namespace ShardingCore.DynamicDataSources
}
catch (Exception e)
{
if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault())
if (!_entityConfigOptions.IgnoreCreateTableError.GetValueOrDefault())
{
_logger.LogWarning(e,
$"table :{virtualTable.GetVirtualTableName()}{entityMetadata.TableSeparator}{tail} will created.");
@ -154,15 +140,15 @@ namespace ShardingCore.DynamicDataSources
}
}
return _shardingConfigOption.CreateShardingTableOnStart.GetValueOrDefault();
return _entityConfigOptions.CreateShardingTableOnStart.GetValueOrDefault();
}
private void EnsureCreated(DbContext context, string dataSourceName)
private void EnsureCreated(IVirtualDataSource<TShardingDbContext> virtualDataSource, DbContext context, string dataSourceName)
{
if (context is IShardingDbContext shardingDbContext)
{
var dbContext = shardingDbContext.GetDbContext(dataSourceName, false, _routeTailFactory.Create(string.Empty));
var isDefault = _virtualDataSource.IsDefault(dataSourceName);
var isDefault = virtualDataSource.IsDefault(dataSourceName);
var modelCacheSyncObject = dbContext.GetModelCacheSyncObject();

View File

@ -12,11 +12,11 @@ namespace ShardingCore.DynamicDataSources
throw new InvalidOperationException($"{nameof(DynamicDataSourceHelper)} create instance");
}
public static void DynamicAppendDataSource<TShardingDbContext>(string dataSourceName, string connectionString) where TShardingDbContext:DbContext,IShardingDbContext
{
var defaultDataSourceInitializer = ShardingContainer.GetService<IDataSourceInitializer<TShardingDbContext>>();
defaultDataSourceInitializer.InitConfigure(dataSourceName, connectionString,false);
}
//public static void DynamicAppendDataSource<TShardingDbContext>(string dataSourceName, string connectionString) where TShardingDbContext:DbContext,IShardingDbContext
//{
// var defaultDataSourceInitializer = ShardingContainer.GetService<IDataSourceInitializer<TShardingDbContext>>();
// defaultDataSourceInitializer.InitConfigure(dataSourceName, connectionString,false);
//}
}
}

View File

@ -4,6 +4,7 @@ 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
@ -13,9 +14,10 @@ namespace ShardingCore.DynamicDataSources
/// <summary>
///
/// </summary>
/// <param name="virtualDataSource"></param>
/// <param name="dataSourceName"></param>
/// <param name="connectionString"></param>
/// <param name="isOnStart">当前是否是启动时被调用</param>
void InitConfigure(string dataSourceName, string connectionString,bool isOnStart);
void InitConfigure(IVirtualDataSource<TShardingDbContext> virtualDataSource,string dataSourceName, string connectionString,bool isOnStart);
}
}

View File

@ -53,9 +53,7 @@ namespace ShardingCore.EFCores
{
if (null == _virtualDataSource)
{
_virtualDataSource =
(IVirtualDataSource) ShardingContainer.GetService(
typeof(IVirtualDataSource<>).GetGenericType0(_context.GetType()));
_virtualDataSource = _context.GetVirtualDataSource();
}
return _virtualDataSource;

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Extensions
{
public static class ShardingDbContextExtension
{
public static bool IsUseReadWriteSeparation(this IShardingDbContext shardingDbContext)
{
return shardingDbContext.GetVirtualDataSource().UseReadWriteSeparation;
}
}
}

View File

@ -89,7 +89,7 @@ namespace ShardingCore.Extensions
return new Dictionary<string, Dictionary<DbContext, IEnumerable<TEntity>>>();
var entityType = typeof(TEntity);
var routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService(typeof(IVirtualDataSource<>).GetGenericType0(shardingDbContext.GetType()));
var virtualDataSource = shardingDbContext.GetVirtualDataSource();
var entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(shardingDbContext.GetType()));
var dataSourceNames = new Dictionary<string, Dictionary<string, BulkDicEntry<TEntity>>>();
var entitiesArray = entities as TEntity[] ?? entities.ToArray();
@ -245,7 +245,7 @@ namespace ShardingCore.Extensions
public static IDictionary<string, IEnumerable<DbContext>> BulkShardingExpression<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext, Expression<Func<TEntity, bool>> where) where TEntity : class
where TShardingDbContext : DbContext, IShardingDbContext
{
var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService(typeof(IVirtualDataSource<>).GetGenericType0(shardingDbContext.GetType()));
var virtualDataSource = shardingDbContext.GetVirtualDataSource();
var routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
var virtualTableManager = (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(shardingDbContext.GetType()));
var entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(shardingDbContext.GetType()));

View File

@ -85,9 +85,7 @@ namespace ShardingCore.Extensions
if (shardingDbContext is ISupportShardingReadWrite shardingReadWrite)
{
var shardingDbContextType = shardingDbContext.GetType();
var shardingConfigOption = ShardingContainer.GetRequiredShardingConfigOption(shardingDbContextType);
var useReadWrite=shardingConfigOption?.UseReadWrite ?? false;
if (useReadWrite)
if (shardingDbContext.IsUseReadWriteSeparation())
{
var shardingReadWriteManager = ShardingContainer.GetService<IShardingReadWriteManager>();
var shardingReadWriteContext = shardingReadWriteManager.GetCurrent(shardingDbContextType);

View File

@ -38,10 +38,6 @@ namespace ShardingCore.Extensions
return virtualDataSource.RouteTo(typeof(TEntity),
new ShardingDataSourceRouteConfig(shardingKeyValue:shardingKeyValue))[0];
}
public static IVirtualDataSourceRoute<TEntity> GetRoute<TEntity>(this IVirtualDataSource virtualDataSource) where TEntity : class
{
return (IVirtualDataSourceRoute<TEntity>)virtualDataSource.GetRoute(typeof(TEntity));
}
}
}

View File

@ -13,6 +13,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
namespace ShardingCore.Sharding
{
@ -83,6 +84,11 @@ namespace ShardingCore.Sharding
return ShardingDbContextExecutor.CreateGenericDbContext(entity);
}
public IVirtualDataSource GetVirtualDataSource()
{
return ShardingDbContextExecutor.GetVirtualDataSource();
}
public override EntityEntry Add(object entity)
{

View File

@ -13,7 +13,7 @@ namespace ShardingCore.Sharding.Abstractions
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public interface IConnectionStringManager<TShardingDbContext> where TShardingDbContext:DbContext,IShardingDbContext
public interface IConnectionStringManager
{
string GetConnectionString(string dataSourceName);
}

View File

@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using System;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
namespace ShardingCore.Sharding.Abstractions
{
@ -29,6 +30,8 @@ namespace ShardingCore.Sharding.Abstractions
/// <returns></returns>
DbContext CreateGenericDbContext<T>(T entity) where T : class;
IVirtualDataSource GetVirtualDataSource();
}
}

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Sharding.ShardingDbContextExecutors;
namespace ShardingCore.Sharding.Abstractions
@ -52,6 +53,8 @@ namespace ShardingCore.Sharding.Abstractions
/// <returns></returns>
DbContext CreateGenericDbContext<TEntity>(TEntity entity) where TEntity : class;
IVirtualDataSource GetVirtualDataSource();
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,

View File

@ -19,30 +19,26 @@ namespace ShardingCore.Sharding
*/
public class ActualConnectionStringManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly IConnectionStringManager<TShardingDbContext> _connectionStringManager;
private readonly IReadWriteOptions<TShardingDbContext> _readWriteOptions;
private readonly bool _useReadWriteSeparation;
private readonly IShardingReadWriteManager _shardingReadWriteManager;
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
public int ReadWriteSeparationPriority { get; set; }
public bool ReadWriteSeparation { get; set; }
public ReadStrategyEnum ReadStrategy { get; set; }
public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; set; }
private string _cacheConnectionString;
public ActualConnectionStringManager()
public ActualConnectionStringManager(IVirtualDataSource<TShardingDbContext> virtualDataSource)
{
_virtualDataSource=ShardingContainer.GetService<IVirtualDataSource<TShardingDbContext>>();
_connectionStringManager = ShardingContainer.GetService<IConnectionStringManager<TShardingDbContext>>();
_virtualDataSource=virtualDataSource;
_shardingReadWriteManager = ShardingContainer.GetService<IShardingReadWriteManager>();
_useReadWriteSeparation = _connectionStringManager is ReadWriteConnectionStringManager<TShardingDbContext>;
_useReadWriteSeparation = virtualDataSource.ConnectionStringManager is ReadWriteConnectionStringManager;
if (_useReadWriteSeparation)
{
_readWriteOptions = ShardingContainer.GetService<IReadWriteOptions<TShardingDbContext>>();
if (_readWriteOptions != null)
{
ReadWriteSeparationPriority = _readWriteOptions.ReadWritePriority;
ReadWriteSeparation = _readWriteOptions.ReadWriteSupport;
}
ReadWriteSeparationPriority = virtualDataSource.ConfigurationParams.ReadWriteDefaultPriority.GetValueOrDefault();
ReadWriteSeparation = virtualDataSource.ConfigurationParams.ReadWriteDefaultEnable.GetValueOrDefault();
ReadStrategy = virtualDataSource.ConfigurationParams.ReadStrategy.GetValueOrDefault();
ReadConnStringGetStrategy = virtualDataSource.ConfigurationParams.ReadConnStringGetStrategy.GetValueOrDefault();
}
}
//public bool IsUseReadWriteSeparation()
//{
@ -54,7 +50,7 @@ namespace ShardingCore.Sharding
return GetWriteConnectionString(dataSourceName);
if (!_useReadWriteSeparation)
{
return _connectionStringManager.GetConnectionString(dataSourceName);
return _virtualDataSource.ConnectionStringManager.GetConnectionString(dataSourceName);
}
else
{
@ -85,19 +81,19 @@ namespace ShardingCore.Sharding
}
private string GetReadWriteSeparationConnectString0(string dataSourceName)
{
if (_readWriteOptions.ReadConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestFirstTime)
if (ReadConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestFirstTime)
{
if (_cacheConnectionString == null)
_cacheConnectionString = _connectionStringManager.GetConnectionString(dataSourceName);
_cacheConnectionString = _virtualDataSource.ConnectionStringManager.GetConnectionString(dataSourceName);
return _cacheConnectionString;
}
else if (_readWriteOptions.ReadConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestEveryTime)
else if (ReadConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestEveryTime)
{
return _connectionStringManager.GetConnectionString(dataSourceName);
return _virtualDataSource.ConnectionStringManager.GetConnectionString(dataSourceName);
}
else
{
throw new ShardingCoreInvalidOperationException($"ReadWriteConnectionStringManager:{_readWriteOptions.ReadConnStringGetStrategy}");
throw new ShardingCoreInvalidOperationException($"ReadWriteConnectionStringManager ReadConnStringGetStrategy:{ReadConnStringGetStrategy}");
}
}

View File

@ -11,17 +11,19 @@ namespace ShardingCore.Sharding
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class DefaultConnectionStringManager<TShardingDbContext> : IConnectionStringManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class DefaultConnectionStringManager : IConnectionStringManager
{
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
private readonly IVirtualDataSource _virtualDataSource;
public DefaultConnectionStringManager(IVirtualDataSource<TShardingDbContext> virtualDataSource)
public DefaultConnectionStringManager(IVirtualDataSource virtualDataSource)
{
_virtualDataSource = virtualDataSource;
}
public string GetConnectionString(string dataSourceName)
{
return _virtualDataSource.GetConnectionString(dataSourceName);
if (_virtualDataSource.IsDefault(dataSourceName))
return _virtualDataSource.DefaultConnectionString;
return _virtualDataSource.GetPhysicDataSource(dataSourceName).ConnectionString;
}
}
}

View File

@ -34,14 +34,12 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
private readonly StreamMergeContext<TEntity> _streamMergeContext;
private readonly IShardingPageManager _shardingPageManager;
private readonly IVirtualTableManager<TShardingDbContext> _virtualTableManager;
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private EnumeratorStreamMergeEngineFactory(StreamMergeContext<TEntity> streamMergeContext)
{
_streamMergeContext = streamMergeContext;
_shardingPageManager = ShardingContainer.GetService<IShardingPageManager>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDbContext>>();
_virtualDataSource = ShardingContainer.GetService<IVirtualDataSource<TShardingDbContext>>();
_entityMetadataManager = ShardingContainer.GetService<IEntityMetadataManager<TShardingDbContext>>();
}
@ -50,6 +48,10 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
return new EnumeratorStreamMergeEngineFactory<TShardingDbContext, TEntity>(streamMergeContext);
}
public IVirtualDataSourceRoute GetRoute(Type entityType)
{
return _streamMergeContext.GetShardingDbContext().GetVirtualDataSource().GetRoute(entityType);
}
public IEnumeratorStreamMergeEngine<TEntity> GetMergeEngine()
{
if (_streamMergeContext.IsRouteNotMatch())
@ -63,7 +65,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
}
//未开启系统分表或者本次查询涉及多张分表
if (_streamMergeContext.IsPaginationQuery() && _streamMergeContext.IsSupportPaginationQuery<TShardingDbContext,TEntity>() && _shardingPageManager.Current != null)
if (_streamMergeContext.IsPaginationQuery() && _streamMergeContext.IsSupportPaginationQuery<TShardingDbContext, TEntity>() && _shardingPageManager.Current != null)
{
//获取虚拟表判断是否启用了分页配置
var shardingEntityType = _streamMergeContext.QueryEntities.FirstOrDefault(o => _entityMetadataManager.IsShardingDataSource(o) || _entityMetadataManager.IsShardingTable(o));
@ -100,7 +102,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
PaginationSequenceConfig tableSequenceOrderConfig = null;
if (isShardingDataSource)
{
var virtualDataSourceRoute = _virtualDataSource.GetRoute(shardingEntityType);
var virtualDataSourceRoute = GetRoute(shardingEntityType);
if (virtualDataSourceRoute.EnablePagination)
{
dataSourceSequenceOrderConfig = virtualDataSourceRoute.PaginationMetadata.PaginationConfigs.OrderByDescending(o => o.AppendOrder)
@ -146,7 +148,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
bool tableUseReverse = true;
if (isShardingDataSource)
{
virtualDataSourceRoute = _virtualDataSource.GetRoute(shardingEntityType);
virtualDataSourceRoute = GetRoute(shardingEntityType);
if (virtualDataSourceRoute.EnablePagination)
{
dataSourceSequenceOrderConfig = orderCount == 1 ? GetPaginationFullMatch(virtualDataSourceRoute.PaginationMetadata.PaginationConfigs, primaryOrder) : GetPaginationPrimaryMatch(virtualDataSourceRoute.PaginationMetadata.PaginationConfigs, primaryOrder);
@ -164,14 +166,14 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
var useSequenceEnumeratorMergeEngine = isShardingDataSource && (dataSourceSequenceOrderConfig != null ||
(isShardingTable &&
!_streamMergeContext.IsCrossDataSource)) || (!isShardingDataSource&&isShardingTable && tableSequenceOrderConfig != null);
!_streamMergeContext.IsCrossDataSource)) || (!isShardingDataSource && isShardingTable && tableSequenceOrderConfig != null);
if (useSequenceEnumeratorMergeEngine)
{
return new SequenceEnumeratorAsyncStreamMergeEngine<TShardingDbContext, TEntity>(_streamMergeContext, dataSourceSequenceOrderConfig, tableSequenceOrderConfig, _shardingPageManager.Current.RouteQueryResults, primaryOrder.IsAsc);
}
var total = _shardingPageManager.Current.RouteQueryResults.Sum(o => o.QueryResult);
if (isShardingDataSource&& virtualDataSourceRoute.EnablePagination)
if (isShardingDataSource && virtualDataSourceRoute.EnablePagination)
{
dataSourceUseReverse =
EntityDataSourceUseReverseShardingPage(virtualDataSourceRoute, total);
@ -181,7 +183,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
tableUseReverse =
EntityTableReverseShardingPage(virtualTable, total);
}
//skip过大reserve skip
if (dataSourceUseReverse && tableUseReverse)
@ -196,7 +198,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
return null;
}
private bool EntityDataSourceUseReverseShardingPage( IVirtualDataSourceRoute virtualDataSourceRoute,long total)
private bool EntityDataSourceUseReverseShardingPage(IVirtualDataSourceRoute virtualDataSourceRoute, long total)
{
if (virtualDataSourceRoute.PaginationMetadata.EnableReverseShardingPage && _streamMergeContext.Take.GetValueOrDefault() > 0)
{
@ -207,7 +209,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
}
return false;
}
private bool EntityTableReverseShardingPage( IVirtualTable virtualTable, long total)
private bool EntityTableReverseShardingPage(IVirtualTable virtualTable, long total)
{
if (virtualTable.PaginationMetadata.EnableReverseShardingPage && _streamMergeContext.Take.GetValueOrDefault() > 0)
{

View File

@ -10,6 +10,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions
{
public interface IReadWriteConnectorFactory
{
IReadWriteConnector CreateConnector<TShardingDbContext>(ReadStrategyEnum strategy, string dataSourceName, IEnumerable<string> connectionStrings) where TShardingDbContext:DbContext,IShardingDbContext;
IReadWriteConnector CreateConnector(ReadStrategyEnum strategy, string dataSourceName,
IEnumerable<string> connectionStrings);
}
}

View File

@ -1,30 +1,30 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
//using System;
//using System.Collections.Generic;
//using System.Text;
//using Microsoft.EntityFrameworkCore;
//using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/7 11:13:52
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public interface IReadWriteOptions<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
{
/// <summary>
/// 默认读写配置优先级
/// </summary>
int ReadWritePriority { get; }
/// <summary>
/// 默认是否开启读写分离
/// </summary>
bool ReadWriteSupport { get; }
ReadStrategyEnum ReadStrategy { get; }
ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; }
}
}
//namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions
//{
// /*
// * @Author: xjm
// * @Description:
// * @Date: 2021/9/7 11:13:52
// * @Ver: 1.0
// * @Email: 326308290@qq.com
// */
// public interface IReadWriteOptions<TShardingDbContext>
// where TShardingDbContext : DbContext, IShardingDbContext
// {
// /// <summary>
// /// 默认读写配置优先级
// /// </summary>
// int ReadWritePriority { get; }
// /// <summary>
// /// 默认是否开启读写分离
// /// </summary>
// bool ReadWriteSupport { get; }
// ReadStrategyEnum ReadStrategy { get; }
// ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; }
// }
//}

View File

@ -16,9 +16,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions
/// <summary>
/// 读写分离链接字符串解析
/// </summary>
/// <typeparam name="TShardingDbContext"></typeparam>
public interface IShardingConnectionStringResolver<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
public interface IShardingConnectionStringResolver
{
bool ContainsReadWriteDataSourceName(string dataSourceName);
string GetConnectionString(string dataSourceName);

View File

@ -16,16 +16,18 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ReadWriteConnectionStringManager<TShardingDbContext> : IConnectionStringManager<TShardingDbContext>, IReadWriteAppendConnectionString where TShardingDbContext : DbContext, IShardingDbContext
public class ReadWriteConnectionStringManager: IConnectionStringManager, IReadWriteAppendConnectionString
{
private IShardingConnectionStringResolver<TShardingDbContext> _shardingConnectionStringResolver;
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
private IShardingConnectionStringResolver _shardingConnectionStringResolver;
private readonly IVirtualDataSource _virtualDataSource;
public ReadWriteConnectionStringManager(IShardingConnectionStringResolver<TShardingDbContext> shardingConnectionStringResolver,IVirtualDataSource<TShardingDbContext> virtualDataSource)
public ReadWriteConnectionStringManager(IVirtualDataSource virtualDataSource)
{
_shardingConnectionStringResolver = shardingConnectionStringResolver;
_virtualDataSource = virtualDataSource;
var readWriteConnectorFactory = ShardingContainer.GetService<IReadWriteConnectorFactory>();
var readWriteConnectors = virtualDataSource.ConfigurationParams.ReadWriteSeparationConfigs.Select(o=> readWriteConnectorFactory.CreateConnector(virtualDataSource.ConfigurationParams.ReadStrategy.GetValueOrDefault(), o.Key,o.Value));
_shardingConnectionStringResolver = new ReadWriteShardingConnectionStringResolver(readWriteConnectors, virtualDataSource.ConfigurationParams.ReadStrategy.GetValueOrDefault());
}
public string GetConnectionString(string dataSourceName)
{

View File

@ -12,25 +12,21 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations
{
public class ReadWriteConnectorFactory: IReadWriteConnectorFactory
{
public IReadWriteConnector CreateConnector<TShardingDbContext>(ReadStrategyEnum strategy,string dataSourceName, IEnumerable<string> connectionStrings) where TShardingDbContext : DbContext, IShardingDbContext
public IReadWriteConnector CreateConnector(ReadStrategyEnum strategy,string dataSourceName, IEnumerable<string> connectionStrings)
{
var readWriteOptions = ShardingContainer.GetService<IReadWriteOptions<TShardingDbContext>>();
if (readWriteOptions == null)
throw new ShardingCoreInvalidOperationException(
"cant create read write connector should use read write");
if (readWriteOptions.ReadStrategy == ReadStrategyEnum.Loop)
if (strategy == ReadStrategyEnum.Loop)
{
return new ReadWriteLoopConnector(dataSourceName, connectionStrings);
}
else if (readWriteOptions.ReadStrategy == ReadStrategyEnum.Random)
else if (strategy == ReadStrategyEnum.Random)
{
return new ReadWriteRandomConnector(dataSourceName, connectionStrings);
}
else
{
throw new ShardingCoreInvalidOperationException(
$"unknown read write strategy:[{readWriteOptions.ReadStrategy}]");
$"unknown read write strategy:[{strategy}]");
}
}
}

View File

@ -1,41 +1,41 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
//using System;
//using System.Collections.Generic;
//using System.Text;
//using Microsoft.EntityFrameworkCore;
//using ShardingCore.Sharding.Abstractions;
//using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
namespace ShardingCore.Sharding.ReadWriteConfigurations
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/7 11:06:40
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
//namespace ShardingCore.Sharding.ReadWriteConfigurations
//{
// /*
// * @Author: xjm
// * @Description:
// * @Date: 2021/9/7 11:06:40
// * @Ver: 1.0
// * @Email: 326308290@qq.com
// */
public class ReadWriteOptions<TShardingDbContext> : IReadWriteOptions<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
{
public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadStrategyEnum readStrategy, ReadConnStringGetStrategyEnum readConnStringGetStrategy)
{
ReadWritePriority = readWritePriority;
ReadWriteSupport = readWriteSupport;
ReadStrategy = readStrategy;
ReadConnStringGetStrategy = readConnStringGetStrategy;
}
public Type ShardingDbContextType => typeof(TShardingDbContext);
/// <summary>
/// 默认读写配置优先级
/// </summary>
public int ReadWritePriority { get; }
/// <summary>
/// 默认是否开启读写分离
/// </summary>
public bool ReadWriteSupport { get; }
// public class ReadWriteOptions<TShardingDbContext> : IReadWriteOptions<TShardingDbContext>
// where TShardingDbContext : DbContext, IShardingDbContext
// {
// public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadStrategyEnum readStrategy, ReadConnStringGetStrategyEnum readConnStringGetStrategy)
// {
// ReadWritePriority = readWritePriority;
// ReadWriteSupport = readWriteSupport;
// ReadStrategy = readStrategy;
// ReadConnStringGetStrategy = readConnStringGetStrategy;
// }
// public Type ShardingDbContextType => typeof(TShardingDbContext);
// /// <summary>
// /// 默认读写配置优先级
// /// </summary>
// public int ReadWritePriority { get; }
// /// <summary>
// /// 默认是否开启读写分离
// /// </summary>
// public bool ReadWriteSupport { get; }
public ReadStrategyEnum ReadStrategy { get; }
public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; }
}
}
// public ReadStrategyEnum ReadStrategy { get; }
// public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; }
// }
//}

View File

@ -11,15 +11,17 @@ using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
namespace ShardingCore.Sharding.ReadWriteConfigurations
{
public class ReadWriteShardingConnectionStringResolver<TShardingDbContext> : IShardingConnectionStringResolver<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class ReadWriteShardingConnectionStringResolver : IShardingConnectionStringResolver
{
private readonly ReadStrategyEnum _readStrategy;
private readonly ConcurrentDictionary<string, IReadWriteConnector> _connectors =
new ConcurrentDictionary<string, IReadWriteConnector>();
private readonly IReadWriteOptions<TShardingDbContext> _readWriteOptions;
private readonly IReadWriteConnectorFactory _readWriteConnectorFactory;
public ReadWriteShardingConnectionStringResolver(IEnumerable<IReadWriteConnector> connectors)
public ReadWriteShardingConnectionStringResolver(IEnumerable<IReadWriteConnector> connectors, ReadStrategyEnum readStrategy)
{
_readStrategy = readStrategy;
var enumerator = connectors.GetEnumerator();
while (enumerator.MoveNext())
{
@ -28,7 +30,6 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations
_connectors.TryAdd(currentConnector.DataSourceName, currentConnector);
}
_readWriteOptions = ShardingContainer.GetService<IReadWriteOptions<TShardingDbContext>>();
_readWriteConnectorFactory = ShardingContainer.GetService<IReadWriteConnectorFactory>();
}
@ -48,7 +49,7 @@ namespace ShardingCore.Sharding.ReadWriteConfigurations
{
if (!_connectors.TryGetValue(dataSourceName, out var connector))
{
connector = _readWriteConnectorFactory.CreateConnector<TShardingDbContext>(_readWriteOptions.ReadStrategy,
connector = _readWriteConnectorFactory.CreateConnector(_readStrategy,
dataSourceName, new List<string>()
{
connectionString

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
/*
* @Author: xjm
@ -31,12 +28,4 @@ namespace ShardingCore.Sharding.ShardingComparision.Abstractions
/// <returns></returns>
object CreateComparer(Type comparerType);
}
/// <summary>
/// 泛型比较器用于依赖注入
/// </summary>
/// <typeparam name="TShardingDbContext"></typeparam>
public interface IShardingComparer<TShardingDbContext> : IShardingComparer where TShardingDbContext:DbContext,IShardingDbContext
{
}
}

View File

@ -15,9 +15,9 @@ namespace ShardingCore.Sharding.ShardingComparision
* @Date: Sunday, 31 October 2021 15:39:46
* @Email: 326308290@qq.com
*/
public class CSharpLanguageShardingComparer<TShardingDbContext> : IShardingComparer<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class CSharpLanguageShardingComparer : IShardingComparer
{
private readonly ConcurrentDictionary<Type, object> _comparers = new ConcurrentDictionary<Type, object>();
private readonly ConcurrentDictionary<Type, object> _comparers = new ();
public virtual int Compare(IComparable x, IComparable y, bool asc)
{
if (x is Guid xg && y is Guid yg)

View File

@ -61,13 +61,13 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors
public ShardingDbContextExecutor(DbContext shardingDbContext)
{
_shardingDbContext = shardingDbContext;
_virtualDataSource = ShardingContainer.GetService<IVirtualDataSource<TShardingDbContext>>();
_virtualDataSource = ShardingContainer.GetRequiredVirtualDataSource<TShardingDbContext>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDbContext>>();
_shardingDbContextFactory = ShardingContainer.GetService<IShardingDbContextFactory<TShardingDbContext>>();
_shardingDbContextOptionsBuilderConfig = ShardingContainer.GetService<IShardingDbContextOptionsBuilderConfig<TShardingDbContext>>();
_entityMetadataManager = ShardingContainer.GetService<IEntityMetadataManager<TShardingDbContext>>();
_routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
_actualConnectionStringManager = new ActualConnectionStringManager<TShardingDbContext>();
_actualConnectionStringManager = new ActualConnectionStringManager<TShardingDbContext>(_virtualDataSource);
}
#region create db context
@ -116,6 +116,11 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors
return CreateDbContext(false, dataSourceName, _routeTailFactory.Create(tail));
}
public IVirtualDataSource GetVirtualDataSource()
{
return _virtualDataSource;
}
private string GetDataSourceName<TEntity>(TEntity entity) where TEntity : class
{
if (!_entityMetadataManager.IsShardingDataSource(entity.GetType()))

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Sharding
{
public class ShardingDbContextOptionsBuilderConfigure<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
public ShardingDbContextOptionsBuilderConfigure(Action<DbConnection, DbContextOptionsBuilder> sameConnectionDbContextOptionsCreator, Action<string, DbContextOptionsBuilder> defaultQueryDbContextOptionsCreator)
{
SameConnectionDbContextOptionsCreator = sameConnectionDbContextOptionsCreator;
DefaultQueryDbContextOptionsCreator = defaultQueryDbContextOptionsCreator;
}
public Action<DbConnection, DbContextOptionsBuilder> SameConnectionDbContextOptionsCreator { get; }
public Action<string, DbContextOptionsBuilder> DefaultQueryDbContextOptionsCreator { get; }
public DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection, DbContextOptionsBuilder dbContextOptionsBuilder)
{
SameConnectionDbContextOptionsCreator(dbConnection, dbContextOptionsBuilder);
dbContextOptionsBuilder.UseInnerDbContextSharding<TShardingDbContext>();
return dbContextOptionsBuilder;
}
public DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString, DbContextOptionsBuilder dbContextOptionsBuilder)
{
DefaultQueryDbContextOptionsCreator(connectionString, dbContextOptionsBuilder);
dbContextOptionsBuilder.UseInnerDbContextSharding<TShardingDbContext>();
return dbContextOptionsBuilder;
}
}
}

View File

@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Query.Internal;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Extensions;
@ -24,7 +25,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
private readonly Expression _queryExpression;
private readonly IEntityMetadataManager _entityMetadataManager;
private readonly Type _shardingDbContextType;
private readonly IShardingConfigOption _shardingConfigOption;
private readonly IShardingEntityConfigOptions _entityConfigOptions;
private QueryCompilerExecutor _queryCompilerExecutor;
private bool? hasQueryCompilerExecutor;
private bool? _isNoTracking;
@ -39,10 +40,9 @@ namespace ShardingCore.Sharding.ShardingExecutors
_queryExpression = queryExpression;
_entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(_shardingDbContextType));
_shardingConfigOption = ShardingContainer.GetRequiredShardingConfigOption(_shardingDbContextType);
_entityConfigOptions = ShardingContainer.GetRequiredShardingEntityConfigOption(_shardingDbContextType);
//原生对象的原生查询如果是读写分离就需要启用并行查询
_isParallelQuery =
_shardingConfigOption.UseReadWrite && _shardingDbContext.CurrentIsReadWriteSeparation();
_isParallelQuery = shardingDbContext.IsUseReadWriteSeparation() && _shardingDbContext.CurrentIsReadWriteSeparation();
}
public static QueryCompilerContext Create(IShardingDbContext shardingDbContext, Expression queryExpression)
@ -103,8 +103,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
hasQueryCompilerExecutor = _queryEntities.All(o => !_entityMetadataManager.IsSharding(o));
if (hasQueryCompilerExecutor.Value)
{
var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService(
typeof(IVirtualDataSource<>).GetGenericType0(_shardingDbContextType));
var virtualDataSource = _shardingDbContext.GetVirtualDataSource();
var routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
var dbContext = _shardingDbContext.GetDbContext(virtualDataSource.DefaultDataSourceName, IsParallelQuery(), routeTailFactory.Create(string.Empty));
_queryCompilerExecutor = new QueryCompilerExecutor(dbContext, _queryExpression);

View File

@ -43,7 +43,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
var dataSourceRouteRuleEngineFactory = (IDataSourceRouteRuleEngineFactory)ShardingContainer.GetService(typeof(IDataSourceRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
var tableRouteRuleEngineFactory = (ITableRouteRuleEngineFactory)ShardingContainer.GetService(typeof(ITableRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
var queryCombineResult = queryableCombine.Combine(queryCompilerContext);
var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable());
var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable(),shardingDbContext);
var tableRouteResults = tableRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable());
var routeResults = tableRouteResults as TableRouteResult[] ?? tableRouteResults.ToArray();
var mergeCombineCompilerContext = MergeQueryCompilerContext.Create(queryCompilerContext, queryCombineResult, dataSourceRouteResult,

View File

@ -17,6 +17,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Exceptions;
@ -65,11 +66,10 @@ namespace ShardingCore.Sharding
public bool IsCrossTable { get; }
private readonly ITrackerManager _trackerManager;
private readonly IShardingConfigOption _shardingConfigOption;
private readonly IShardingEntityConfigOptions _shardingEntityConfigOptions;
private readonly ConcurrentDictionary<DbContext, object> _parallelDbContexts;
private readonly IShardingComparer _shardingComparer;
public StreamMergeContext(IMergeQueryCompilerContext mergeQueryCompilerContext,
IRouteTailFactory routeTailFactory)
@ -94,9 +94,8 @@ namespace ShardingCore.Sharding
_trackerManager =
(ITrackerManager)ShardingContainer.GetService(
typeof(ITrackerManager<>).GetGenericType0(mergeQueryCompilerContext.GetShardingDbContextType()));
_shardingComparer = (IShardingComparer)ShardingContainer.GetService(typeof(IShardingComparer<>).GetGenericType0(_shardingDbContext.GetType()));
_shardingConfigOption = ShardingContainer.GetRequiredShardingConfigOption(mergeQueryCompilerContext.GetShardingDbContextType());
_shardingEntityConfigOptions = ShardingContainer.GetRequiredShardingEntityConfigOption(mergeQueryCompilerContext.GetShardingDbContextType());
_parallelDbContexts = new ConcurrentDictionary<DbContext, object>();
}
public void ReSetOrders(IEnumerable<PropertyOrder> orders)
@ -197,7 +196,7 @@ namespace ShardingCore.Sharding
public int GetMaxQueryConnectionsLimit()
{
return _shardingConfigOption.MaxQueryConnectionsLimit;
return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit;
}
public ConnectionModeEnum GetConnectionMode(int sqlCount)
{
@ -206,13 +205,13 @@ namespace ShardingCore.Sharding
private ConnectionModeEnum CalcConnectionMode(int sqlCount)
{
switch (_shardingConfigOption.ConnectionMode)
switch (_shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode)
{
case ConnectionModeEnum.MEMORY_STRICTLY:
case ConnectionModeEnum.CONNECTION_STRICTLY: return _shardingConfigOption.ConnectionMode;
case ConnectionModeEnum.CONNECTION_STRICTLY: return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode;
default:
{
return _shardingConfigOption.MaxQueryConnectionsLimit < sqlCount
return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit < sqlCount
? ConnectionModeEnum.CONNECTION_STRICTLY
: ConnectionModeEnum.MEMORY_STRICTLY; ;
}
@ -224,7 +223,7 @@ namespace ShardingCore.Sharding
/// <returns></returns>
private bool IsUseReadWriteSeparation()
{
return _shardingConfigOption.UseReadWrite&&_shardingDbContext.CurrentIsReadWriteSeparation();
return _shardingDbContext.IsUseReadWriteSeparation()&&_shardingDbContext.CurrentIsReadWriteSeparation();
}
/// <summary>
@ -253,7 +252,7 @@ namespace ShardingCore.Sharding
public IShardingComparer GetShardingComparer()
{
return _shardingComparer;
return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.ShardingComparer;
}
public TResult PreperExecute<TResult>(Func<TResult> emptyFunc)
@ -296,7 +295,7 @@ namespace ShardingCore.Sharding
private bool ThrowIfQueryRouteNotMatch()
{
return _shardingConfigOption.ThrowIfQueryRouteNotMatch;
return _shardingEntityConfigOptions.ThrowIfQueryRouteNotMatch;
}
public void Dispose()
{

View File

@ -35,14 +35,8 @@ namespace ShardingCore
public readonly ISet<ParallelTableGroupNode> _parallelTables = new HashSet<ParallelTableGroupNode>();
public Action<DbConnection, DbContextOptionsBuilder> SameConnectionConfigure { get; private set; }
public Action<string, DbContextOptionsBuilder> DefaultQueryConfigure { get; private set; }
public Func<IServiceProvider, IDictionary<string, string>> DataSourcesConfigure { get; private set; }
public void UseShardingQuery(Action<string, DbContextOptionsBuilder> queryConfigure)
{
DefaultQueryConfigure = queryConfigure ?? throw new ArgumentNullException(nameof(queryConfigure));
}
public void UseShardingTransaction(Action<DbConnection, DbContextOptionsBuilder> transactionConfigure)
{
SameConnectionConfigure = transactionConfigure ?? throw new ArgumentNullException(nameof(transactionConfigure));
@ -53,13 +47,13 @@ namespace ShardingCore
DataSourcesConfigure = dataSourcesConfigure ?? throw new ArgumentNullException(nameof(dataSourcesConfigure));
}
public Func<IServiceProvider, IShardingComparer<TShardingDbContext>> ReplaceShardingComparerFactory { get; private set; } = sp => new CSharpLanguageShardingComparer<TShardingDbContext>();
public Func<IServiceProvider, IShardingComparer> ReplaceShardingComparerFactory { get; private set; } = sp => new CSharpLanguageShardingComparer();
/// <summary>
/// 替换默认的比较器
/// </summary>
/// <param name="newShardingComparerFactory"></param>
/// <exception cref="ArgumentNullException"></exception>
public void ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer<TShardingDbContext>> newShardingComparerFactory)
public void ReplaceShardingComparer(Func<IServiceProvider, IShardingComparer> newShardingComparerFactory)
{
ReplaceShardingComparerFactory=newShardingComparerFactory ?? throw new ArgumentNullException(nameof(newShardingComparerFactory));
}
@ -79,8 +73,8 @@ namespace ShardingCore
//public void UseShardingOptionsBuilder(Action<DbConnection, DbContextOptionsBuilder> sameConnectionConfigure, Action<string,DbContextOptionsBuilder> defaultQueryConfigure = null)
//{
// SameConnectionConfigure = sameConnectionConfigure ?? throw new ArgumentNullException(nameof(sameConnectionConfigure));
// DefaultQueryConfigure = defaultQueryConfigure ?? throw new ArgumentNullException(nameof(defaultQueryConfigure));
// ConnectionConfigure = sameConnectionConfigure ?? throw new ArgumentNullException(nameof(sameConnectionConfigure));
// ConnectionStringConfigure = defaultQueryConfigure ?? throw new ArgumentNullException(nameof(defaultQueryConfigure));
//}
public bool UseReadWrite => ReadConnStringConfigure != null;

View File

@ -7,6 +7,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
namespace ShardingCore
{
@ -108,14 +111,42 @@ namespace ShardingCore
return Activator.CreateInstance(serviceType, @params);
}
public static IShardingConfigOption<TShardingDbContext> GetRequiredShardingConfigOption<TShardingDbContext>()
//public static IShardingConfigOption<TShardingDbContext> GetRequiredShardingConfigOption<TShardingDbContext>()
// where TShardingDbContext : DbContext, IShardingDbContext
//{
// return (IShardingConfigOption<TShardingDbContext>)GetRequiredShardingConfigOption(typeof(TShardingDbContext));
//}
//public static IShardingConfigOption GetRequiredShardingConfigOption(Type shardingDbContextType)
//{
// return (IShardingConfigOption)ServiceProvider.GetService(typeof(IShardingConfigOption<>).GetGenericType0(shardingDbContextType));
//}
public static IShardingEntityConfigOptions<TShardingDbContext> GetRequiredShardingEntityConfigOption<TShardingDbContext>()
where TShardingDbContext : DbContext, IShardingDbContext
{
return (IShardingConfigOption<TShardingDbContext>)GetRequiredShardingConfigOption(typeof(TShardingDbContext));
return (IShardingEntityConfigOptions<TShardingDbContext>)GetRequiredShardingEntityConfigOption(typeof(TShardingDbContext));
}
public static IShardingConfigOption GetRequiredShardingConfigOption(Type shardingDbContextType)
public static IShardingEntityConfigOptions GetRequiredShardingEntityConfigOption(Type shardingDbContextType)
{
return (IShardingConfigOption)ServiceProvider.GetService(typeof(IShardingConfigOption<>).GetGenericType0(shardingDbContextType));
return (IShardingEntityConfigOptions)ServiceProvider.GetService(typeof(IShardingEntityConfigOptions<>).GetGenericType0(shardingDbContextType));
}
public static IVirtualDataSourceManager<TShardingDbContext> GetRequiredVirtualDataSourceManager<TShardingDbContext>()
where TShardingDbContext : DbContext, IShardingDbContext
{
return (IVirtualDataSourceManager<TShardingDbContext>)GetRequiredVirtualDataSourceManager(typeof(TShardingDbContext));
}
public static IVirtualDataSourceManager GetRequiredVirtualDataSourceManager(Type shardingDbContextType)
{
return (IVirtualDataSourceManager)ServiceProvider.GetService(typeof(IVirtualDataSourceManager<>).GetGenericType0(shardingDbContextType));
}
public static IVirtualDataSource<TShardingDbContext> GetRequiredVirtualDataSource<TShardingDbContext>()
where TShardingDbContext : DbContext, IShardingDbContext
{
return GetRequiredVirtualDataSourceManager<TShardingDbContext>().GetVirtualDataSource();
}
public static IVirtualDataSource GetRequiredVirtualDataSource(Type shardingDbContextType)
{
return GetRequiredVirtualDataSourceManager(shardingDbContextType).GetVirtualDataSource();
}
}
}

View File

@ -13,6 +13,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
@ -28,14 +29,14 @@ namespace ShardingCore.TableCreator
{
private readonly ILogger<ShardingTableCreator<TShardingDbContext>> _logger;
private readonly IServiceProvider _serviceProvider;
private readonly IShardingConfigOption<TShardingDbContext> _shardingConfigOption;
private readonly IShardingEntityConfigOptions<TShardingDbContext> _entityConfigOptions;
private readonly IRouteTailFactory _routeTailFactory;
public ShardingTableCreator(ILogger<ShardingTableCreator<TShardingDbContext>> logger, IServiceProvider serviceProvider, IShardingConfigOption<TShardingDbContext> shardingConfigOption, IRouteTailFactory routeTailFactory)
public ShardingTableCreator(ILogger<ShardingTableCreator<TShardingDbContext>> logger, IServiceProvider serviceProvider, IShardingEntityConfigOptions<TShardingDbContext> entityConfigOptions, IRouteTailFactory routeTailFactory)
{
_logger = logger;
_serviceProvider = serviceProvider;
_shardingConfigOption = shardingConfigOption;
_entityConfigOptions = entityConfigOptions;
_routeTailFactory = routeTailFactory;
}
@ -77,7 +78,7 @@ namespace ShardingCore.TableCreator
}
catch (Exception ex)
{
if (!_shardingConfigOption.IgnoreCreateTableError.GetValueOrDefault())
if (!_entityConfigOptions.IgnoreCreateTableError.GetValueOrDefault())
{
_logger.LogWarning(ex,
$"create table error entity name:[{shardingEntityType.Name}].");

View File

@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
@ -64,38 +65,42 @@ namespace ShardingCore.VirtualRoutes.Abstractions
return Task.CompletedTask;
}
var entityMetadataManager = (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(EntityMetadata.ShardingDbContextType));
var virtualDataSource = (IVirtualDataSource)ShardingContainer.GetService(typeof(IVirtualDataSource<>).GetGenericType0(EntityMetadata.ShardingDbContextType));
var tableCreator = (IShardingTableCreator)ShardingContainer.GetService(typeof(IShardingTableCreator<>).GetGenericType0(EntityMetadata.ShardingDbContextType));
var virtualDataSourceManager = (IVirtualDataSourceManager)ShardingContainer.GetService(typeof(IVirtualDataSourceManager<>).GetGenericType0(EntityMetadata.ShardingDbContextType));
var allVirtualDataSources = virtualDataSourceManager.GetAllVirtualDataSources();
var now = DateTime.Now.AddMinutes(IncrementMinutes);
var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now);
ISet<string> dataSources = new HashSet<string>();
if (entityMetadataManager.IsShardingDataSource(typeof(TEntity)))
foreach (var virtualDataSource in allVirtualDataSources)
{
var virtualDataSourceRoute = virtualDataSource.GetRoute(typeof(TEntity));
foreach (var dataSourceName in virtualDataSourceRoute.GetAllDataSourceNames())
ISet<string> dataSources = new HashSet<string>();
if (entityMetadataManager.IsShardingDataSource(typeof(TEntity)))
{
dataSources.Add(dataSourceName);
var virtualDataSourceRoute = virtualDataSource.GetRoute(typeof(TEntity));
foreach (var dataSourceName in virtualDataSourceRoute.GetAllDataSourceNames())
{
dataSources.Add(dataSourceName);
}
}
}
else
{
dataSources.Add(virtualDataSource.DefaultDataSourceName);
}
_logger.LogInformation($"auto create table data source names:[{string.Join(",", dataSources)}]");
foreach (var dataSource in dataSources)
{
try
else
{
_logger.LogInformation($"begin table tail:[{tail}],entity:[{typeof(TEntity).Name}]");
tableCreator.CreateTable(dataSource, typeof(TEntity), tail);
_logger.LogInformation($"succeed table tail:[{tail}],entity:[{typeof(TEntity).Name}]");
dataSources.Add(virtualDataSource.DefaultDataSourceName);
}
catch (Exception e)
_logger.LogInformation($"auto create table data source names:[{string.Join(",", dataSources)}]");
foreach (var dataSource in dataSources)
{
//ignore
_logger.LogInformation($"warning table tail:[{tail}],entity:[{typeof(TEntity).Name}]");
if (DoLogError)
_logger.LogError(e, $"{dataSource} {typeof(TEntity).Name}'s create table error ");
try
{
_logger.LogInformation($"begin table tail:[{tail}],entity:[{typeof(TEntity).Name}]");
tableCreator.CreateTable(dataSource, typeof(TEntity), tail);
_logger.LogInformation($"succeed table tail:[{tail}],entity:[{typeof(TEntity).Name}]");
}
catch (Exception e)
{
//ignore
_logger.LogInformation($"warning table tail:[{tail}],entity:[{typeof(TEntity).Name}]");
if (DoLogError)
_logger.LogError(e, $"{dataSource} {typeof(TEntity).Name}'s create table error ");
}
}
}
virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, tail));