This commit is contained in:
parent
ee0f6c1781
commit
773f11266f
19
README.md
19
README.md
|
@ -378,17 +378,28 @@ ctor inject IShardingRouteManager shardingRouteManager
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
## 读写分离
|
## 读写分离
|
||||||
该框架目前已经支持单node的读写分离,后续框架将支持多node的读
|
该框架目前已经支持一主多从的读写分离`UseReadWriteConfiguration`第一个参数返回对应的读数据库链接,默认写数据库链接不会放入其中,并且支持轮询和随机两种读写分离策略,又因为读写分离多链接的时候会导致数据读写不一致,(如分页其实是2步第一步获取count,第二部获取list)会导致数据量在最后几页出现缺量的问题,
|
||||||
|
针对这个问题框架目前实现了自定义读链接获取策略`ReadConnStringGetStrategyEnum.LatestEveryTime`表示为每次都是新的(这个情况下会出现上述问题),`ReadConnStringGetStrategyEnum.LatestFirstTime`表示以dbcontext作为单位获取一次(同dbcontext不会出现问题),
|
||||||
|
又因为各节点读写分离网络等一系列问题会导致刚刚写入的数据没办法获取到所以系统默认在dbcontext上添加是否支持读写分离如果false默认选择写字符串去读取`DbContext.ReadWriteSupport`
|
||||||
|
|
||||||
```c#
|
```c#
|
||||||
|
|
||||||
services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"])
|
services.AddShardingDbContext<DefaultShardingDbContext, DefaultTableDbContext>(
|
||||||
|
o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;")
|
||||||
, op =>
|
, op =>
|
||||||
{
|
{
|
||||||
op.EnsureCreatedWithOutShardingTable = true;
|
op.EnsureCreatedWithOutShardingTable = true;
|
||||||
op.CreateShardingTableOnStart = true;
|
op.CreateShardingTableOnStart = true;
|
||||||
op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),
|
op.UseShardingOptionsBuilder(
|
||||||
(conStr,builder)=> builder.UseSqlServer("read db connection string").UseLoggerFactory(efLogger));
|
(connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),//使用dbconnection创建dbcontext支持事务
|
||||||
|
(conStr,builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
|
||||||
|
//.ReplaceService<IQueryTranslationPostprocessorFactory,SqlServer2008QueryTranslationPostprocessorFactory>()//支持sqlserver2008r2
|
||||||
|
);//使用链接字符串创建dbcontext
|
||||||
|
op.UseReadWriteConfiguration(sp => new List<string>()
|
||||||
|
{
|
||||||
|
"Data Source=localhost;Initial Catalog=ShardingCoreDB1;Integrated Security=True;",
|
||||||
|
"Data Source=localhost;Initial Catalog=ShardingCoreDB2;Integrated Security=True;"
|
||||||
|
}, ReadStrategyEnum.Random);
|
||||||
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
||||||
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
|
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Sample.SqlServer.Shardings
|
||||||
public void Configure(PaginationBuilder<SysUserSalary> builder)
|
public void Configure(PaginationBuilder<SysUserSalary> builder)
|
||||||
{
|
{
|
||||||
builder.PaginationSequence(o => o.Id)
|
builder.PaginationSequence(o => o.Id)
|
||||||
.UseTailCompare(Comparer<string>.Default)
|
.UseTailComparer(Comparer<string>.Default)
|
||||||
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch);
|
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch);
|
||||||
builder.PaginationSequence(o => o.DateOfMonth)
|
builder.PaginationSequence(o => o.DateOfMonth)
|
||||||
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone(10);
|
.UseQueryMatch(PaginationMatchEnum.Owner | PaginationMatchEnum.Named | PaginationMatchEnum.PrimaryMatch).UseAppendIfOrderNone(10);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
@ -11,6 +12,7 @@ using Sample.SqlServer.DbContexts;
|
||||||
using Sample.SqlServer.Shardings;
|
using Sample.SqlServer.Shardings;
|
||||||
using ShardingCore;
|
using ShardingCore;
|
||||||
using ShardingCore.EFCores;
|
using ShardingCore.EFCores;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||||
|
|
||||||
namespace Sample.SqlServer
|
namespace Sample.SqlServer
|
||||||
{
|
{
|
||||||
|
@ -36,9 +38,14 @@ namespace Sample.SqlServer
|
||||||
op.CreateShardingTableOnStart = true;
|
op.CreateShardingTableOnStart = true;
|
||||||
op.UseShardingOptionsBuilder(
|
op.UseShardingOptionsBuilder(
|
||||||
(connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),//使用dbconnection创建dbcontext支持事务
|
(connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),//使用dbconnection创建dbcontext支持事务
|
||||||
(conStr,builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger)
|
(conStr,builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
|
||||||
//.ReplaceService<IQueryTranslationPostprocessorFactory,SqlServer2008QueryTranslationPostprocessorFactory>()//支持sqlserver2008r2
|
//.ReplaceService<IQueryTranslationPostprocessorFactory,SqlServer2008QueryTranslationPostprocessorFactory>()//支持sqlserver2008r2
|
||||||
);//使用链接字符串创建dbcontext
|
);//使用链接字符串创建dbcontext
|
||||||
|
op.UseReadWriteConfiguration(sp => new List<string>()
|
||||||
|
{
|
||||||
|
"Data Source=localhost;Initial Catalog=ShardingCoreDB1;Integrated Security=True;",
|
||||||
|
"Data Source=localhost;Initial Catalog=ShardingCoreDB2;Integrated Security=True;"
|
||||||
|
}, ReadStrategyEnum.Random);
|
||||||
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
||||||
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
|
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
|
||||||
});
|
});
|
||||||
|
|
|
@ -146,6 +146,11 @@ namespace Samples.AbpSharding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public void UseShardingTransaction(DbTransaction transaction)
|
public void UseShardingTransaction(DbTransaction transaction)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
|
@ -19,6 +19,8 @@ using ShardingCore.Core.ShardingPage;
|
||||||
using ShardingCore.Core.ShardingPage.Abstractions;
|
using ShardingCore.Core.ShardingPage.Abstractions;
|
||||||
using ShardingCore.Core.VirtualRoutes;
|
using ShardingCore.Core.VirtualRoutes;
|
||||||
using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
|
using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||||
using ShardingCore.Sharding.ShardingQueryExecutors;
|
using ShardingCore.Sharding.ShardingQueryExecutors;
|
||||||
|
|
||||||
namespace ShardingCore
|
namespace ShardingCore
|
||||||
|
@ -32,7 +34,6 @@ namespace ShardingCore
|
||||||
public static class DIExtension
|
public static class DIExtension
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static IServiceCollection AddShardingDbContext<TShardingDbContext, TActualDbContext>(this IServiceCollection services,
|
public static IServiceCollection AddShardingDbContext<TShardingDbContext, TActualDbContext>(this IServiceCollection services,
|
||||||
Action<DbContextOptionsBuilder> optionsAction = null,
|
Action<DbContextOptionsBuilder> optionsAction = null,
|
||||||
Action<ShardingConfigOption<TShardingDbContext,TActualDbContext>> configure=null,
|
Action<ShardingConfigOption<TShardingDbContext,TActualDbContext>> configure=null,
|
||||||
|
@ -49,14 +50,7 @@ namespace ShardingCore
|
||||||
configure?.Invoke(shardingConfigOptions);
|
configure?.Invoke(shardingConfigOptions);
|
||||||
services.AddSingleton<IShardingConfigOption, ShardingConfigOption<TShardingDbContext, TActualDbContext>>(sp=> shardingConfigOptions);
|
services.AddSingleton<IShardingConfigOption, ShardingConfigOption<TShardingDbContext, TActualDbContext>>(sp=> shardingConfigOptions);
|
||||||
|
|
||||||
|
services.AddShardingBaseOptions(shardingConfigOptions);
|
||||||
//添加创建TActualDbContext 的 创建者
|
|
||||||
var config = new ShardingDbContextOptionsBuilderConfig<TShardingDbContext>(shardingConfigOptions.SameConnectionConfigure,shardingConfigOptions.DefaultQueryConfigure);
|
|
||||||
services.AddSingleton<IShardingDbContextOptionsBuilderConfig, ShardingDbContextOptionsBuilderConfig<TShardingDbContext>>(sp=> config);
|
|
||||||
|
|
||||||
//添加创建TActualDbContext创建者
|
|
||||||
services.AddSingleton<IShardingDbContextCreatorConfig,DefaultShardingDbContextCreatorConfig<TShardingDbContext, TActualDbContext>>(sp=> new DefaultShardingDbContextCreatorConfig<TShardingDbContext, TActualDbContext>(typeof(TActualDbContext)));
|
|
||||||
|
|
||||||
|
|
||||||
Action<DbContextOptionsBuilder> shardingOptionAction = option =>
|
Action<DbContextOptionsBuilder> shardingOptionAction = option =>
|
||||||
{
|
{
|
||||||
|
@ -93,12 +87,9 @@ namespace ShardingCore
|
||||||
services.AddSingleton<IShardingConfigOption, ShardingConfigOption<TShardingDbContext, TActualDbContext>>(sp=> shardingConfigOptions);
|
services.AddSingleton<IShardingConfigOption, ShardingConfigOption<TShardingDbContext, TActualDbContext>>(sp=> shardingConfigOptions);
|
||||||
|
|
||||||
|
|
||||||
//添加创建TActualDbContext 的 创建者
|
|
||||||
var config = new ShardingDbContextOptionsBuilderConfig<TShardingDbContext>(shardingConfigOptions.SameConnectionConfigure,shardingConfigOptions.DefaultQueryConfigure);
|
|
||||||
services.AddSingleton<IShardingDbContextOptionsBuilderConfig, ShardingDbContextOptionsBuilderConfig<TShardingDbContext>>(sp=> config);
|
|
||||||
|
|
||||||
//添加创建TActualDbContext创建者
|
services.AddShardingBaseOptions(shardingConfigOptions);
|
||||||
services.AddSingleton<IShardingDbContextCreatorConfig,DefaultShardingDbContextCreatorConfig<TShardingDbContext, TActualDbContext>>(sp=> new DefaultShardingDbContextCreatorConfig<TShardingDbContext, TActualDbContext>(typeof(TActualDbContext)));
|
|
||||||
|
|
||||||
|
|
||||||
Action<IServiceProvider, DbContextOptionsBuilder> shardingOptionAction = (sp, option) =>
|
Action<IServiceProvider, DbContextOptionsBuilder> shardingOptionAction = (sp, option) =>
|
||||||
|
@ -119,6 +110,49 @@ namespace ShardingCore
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
internal static void AddShardingBaseOptions<TShardingDbContext, TActualDbContext>(this IServiceCollection services,
|
||||||
|
ShardingConfigOption<TShardingDbContext, TActualDbContext> shardingConfigOptions)
|
||||||
|
where TActualDbContext : DbContext, IShardingTableDbContext
|
||||||
|
where TShardingDbContext : DbContext, IShardingDbContext<TActualDbContext>
|
||||||
|
{
|
||||||
|
|
||||||
|
//添加创建TActualDbContext 的DbContextOptionsBuilder创建者
|
||||||
|
var config = new ShardingDbContextOptionsBuilderConfig<TShardingDbContext>(shardingConfigOptions.SameConnectionConfigure, shardingConfigOptions.DefaultQueryConfigure);
|
||||||
|
services.AddSingleton<IShardingDbContextOptionsBuilderConfig, ShardingDbContextOptionsBuilderConfig<TShardingDbContext>>(sp => config);
|
||||||
|
|
||||||
|
//添加创建TActualDbContext创建者
|
||||||
|
services.AddSingleton<IShardingDbContextCreatorConfig, DefaultShardingDbContextCreatorConfig<TShardingDbContext, TActualDbContext>>(sp => new DefaultShardingDbContextCreatorConfig<TShardingDbContext, TActualDbContext>(typeof(TActualDbContext)));
|
||||||
|
|
||||||
|
if (!shardingConfigOptions.UseReadWrite)
|
||||||
|
{
|
||||||
|
services.AddTransient<IConnectionStringManager, DefaultConnectionStringManager<TShardingDbContext>>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
services.AddTransient<IConnectionStringManager, ReadWriteConnectionStringManager<TShardingDbContext>>();
|
||||||
|
|
||||||
|
services.AddSingleton<IReadWriteOptions, ReadWriteOptions<TShardingDbContext>>(sp=>new ReadWriteOptions<TShardingDbContext>(shardingConfigOptions.ReadWriteDefaultPriority, shardingConfigOptions.ReadWriteDefaultEnable, shardingConfigOptions.ReadConnStringGetStrategy));
|
||||||
|
if (shardingConfigOptions.ReadStrategyEnum == ReadStrategyEnum.Loop)
|
||||||
|
{
|
||||||
|
services
|
||||||
|
.AddSingleton<IShardingConnectionStringResolver,
|
||||||
|
LoopShardingConnectionStringResolver<TShardingDbContext>>(sp =>
|
||||||
|
new LoopShardingConnectionStringResolver<TShardingDbContext>(
|
||||||
|
shardingConfigOptions.ReadConnStringConfigure(sp)));
|
||||||
|
}else if (shardingConfigOptions.ReadStrategyEnum == ReadStrategyEnum.Random)
|
||||||
|
{
|
||||||
|
services
|
||||||
|
.AddSingleton<IShardingConnectionStringResolver,
|
||||||
|
RandomShardingConnectionStringResolver<TShardingDbContext>>(sp =>
|
||||||
|
new RandomShardingConnectionStringResolver<TShardingDbContext>(
|
||||||
|
shardingConfigOptions.ReadConnStringConfigure(sp)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
services.AddSingleton<IShardingReadWriteManager, ShardingReadWriteManager>();
|
||||||
|
services.AddSingleton<IShardingReadWriteAccessor, ShardingReadWriteAccessor<TShardingDbContext>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal static IServiceCollection AddInternalShardingCore(this IServiceCollection services)
|
internal static IServiceCollection AddInternalShardingCore(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
|
@ -61,6 +61,7 @@ namespace ShardingCore.Extensions
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据对象集合解析
|
/// 根据对象集合解析
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace ShardingCore.Helpers
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 14:33:52
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public static class RandomHelper
|
||||||
|
{
|
||||||
|
static int seed = Environment.TickCount;
|
||||||
|
|
||||||
|
static readonly ThreadLocal<Random> random =
|
||||||
|
new ThreadLocal<Random>(() => new Random(Interlocked.Increment(ref seed)));
|
||||||
|
|
||||||
|
public static int Next()
|
||||||
|
{
|
||||||
|
return random.Value.Next();
|
||||||
|
}
|
||||||
|
public static int Next(int max)
|
||||||
|
{
|
||||||
|
return random.Value.Next(max);
|
||||||
|
}
|
||||||
|
public static int Next(int min,int max)
|
||||||
|
{
|
||||||
|
return random.Value.Next(min,max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ namespace ShardingCore
|
||||||
{
|
{
|
||||||
Type ShardingDbContextType { get;}
|
Type ShardingDbContextType { get;}
|
||||||
Type ActualDbContextType { get;}
|
Type ActualDbContextType { get;}
|
||||||
|
bool UseReadWrite { get; }
|
||||||
|
|
||||||
void AddShardingTableRoute<TRoute>() where TRoute : IVirtualTableRoute;
|
void AddShardingTableRoute<TRoute>() where TRoute : IVirtualTableRoute;
|
||||||
Type GetVirtualRouteType(Type entityType);
|
Type GetVirtualRouteType(Type entityType);
|
||||||
|
|
|
@ -10,6 +10,8 @@ using ShardingCore.DbContexts.ShardingDbContexts;
|
||||||
using ShardingCore.Exceptions;
|
using ShardingCore.Exceptions;
|
||||||
using ShardingCore.Extensions;
|
using ShardingCore.Extensions;
|
||||||
using ShardingCore.Sharding.Abstractions;
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -19,8 +21,6 @@ using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using ShardingCore.EFCores;
|
|
||||||
|
|
||||||
namespace ShardingCore.Sharding
|
namespace ShardingCore.Sharding
|
||||||
{
|
{
|
||||||
|
@ -34,17 +34,19 @@ namespace ShardingCore.Sharding
|
||||||
/// 分表分库的dbcontext
|
/// 分表分库的dbcontext
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
public abstract class AbstractShardingDbContext<T> : DbContext, IShardingDbContext<T>, IShardingTransaction where T : DbContext, IShardingTableDbContext
|
public abstract class AbstractShardingDbContext<T> : DbContext, IShardingDbContext<T>, IShardingTransaction,IShardingReadWriteSupport where T : DbContext, IShardingTableDbContext
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, DbContext> _dbContextCaches = new ConcurrentDictionary<string, DbContext>();
|
private readonly ConcurrentDictionary<string, DbContext> _dbContextCaches = new ConcurrentDictionary<string, DbContext>();
|
||||||
|
private readonly IShardingConfigOption shardingConfigOption;
|
||||||
private readonly IVirtualTableManager _virtualTableManager;
|
private readonly IVirtualTableManager _virtualTableManager;
|
||||||
private readonly IRouteTailFactory _routeTailFactory;
|
private readonly IRouteTailFactory _routeTailFactory;
|
||||||
private readonly IShardingDbContextFactory _shardingDbContextFactory;
|
private readonly IShardingDbContextFactory _shardingDbContextFactory;
|
||||||
private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig;
|
private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig;
|
||||||
|
private readonly IReadWriteOptions _readWriteOptions;
|
||||||
|
private readonly IConnectionStringManager _connectionStringManager;
|
||||||
private DbContextOptions<T> _dbContextOptions;
|
private DbContextOptions<T> _dbContextOptions;
|
||||||
|
|
||||||
private readonly object CREATELOCK = new object();
|
private readonly object CREATELOCK = new object();
|
||||||
private Guid idid = Guid.NewGuid();
|
|
||||||
|
|
||||||
public AbstractShardingDbContext(DbContextOptions options) : base(options)
|
public AbstractShardingDbContext(DbContextOptions options) : base(options)
|
||||||
{
|
{
|
||||||
|
@ -53,7 +55,20 @@ namespace ShardingCore.Sharding
|
||||||
_routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
|
_routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
|
||||||
_shardingDbContextOptionsBuilderConfig = ShardingContainer
|
_shardingDbContextOptionsBuilderConfig = ShardingContainer
|
||||||
.GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>()
|
.GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>()
|
||||||
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType);
|
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType)??throw new ArgumentNullException(nameof(IShardingDbContextOptionsBuilderConfig));
|
||||||
|
|
||||||
|
_connectionStringManager = ShardingContainer.GetService<IEnumerable<IConnectionStringManager>>()
|
||||||
|
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType) ?? throw new ArgumentNullException(nameof(IConnectionStringManager));
|
||||||
|
|
||||||
|
shardingConfigOption =ShardingContainer.GetService<IEnumerable<IShardingConfigOption>>().FirstOrDefault(o=>o.ShardingDbContextType==ShardingDbContextType&&o.ActualDbContextType==typeof(T)) ?? throw new ArgumentNullException(nameof(IShardingConfigOption));
|
||||||
|
if (shardingConfigOption.UseReadWrite)
|
||||||
|
{
|
||||||
|
_readWriteOptions = ShardingContainer
|
||||||
|
.GetService<IEnumerable<IReadWriteOptions>>()
|
||||||
|
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType) ?? throw new ArgumentNullException(nameof(IReadWriteOptions));
|
||||||
|
ReadWriteSupport = _readWriteOptions.ReadWriteSupport;
|
||||||
|
ReadWritePriority = _readWriteOptions.ReadWritePriority;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Type ShardingDbContextType { get; }
|
public abstract Type ShardingDbContextType { get; }
|
||||||
|
@ -69,6 +84,23 @@ namespace ShardingCore.Sharding
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
public int ReadWritePriority { get; set; }
|
||||||
|
public bool ReadWriteSupport { get; set; }
|
||||||
|
public ReadConnStringGetStrategyEnum GetReadConnStringGetStrategy()
|
||||||
|
{
|
||||||
|
return _readWriteOptions.ReadConnStringGetStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetWriteConnectionString()
|
||||||
|
{
|
||||||
|
return GetConnectionString();
|
||||||
|
}
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
return Database.GetDbConnection().ConnectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private DbContextOptionsBuilder<T> CreateDbContextOptionBuilder()
|
private DbContextOptionsBuilder<T> CreateDbContextOptionBuilder()
|
||||||
{
|
{
|
||||||
Type type = typeof(DbContextOptionsBuilder<>);
|
Type type = typeof(DbContextOptionsBuilder<>);
|
||||||
|
@ -83,10 +115,10 @@ namespace ShardingCore.Sharding
|
||||||
_shardingDbContextOptionsBuilderConfig.UseDbContextOptionsBuilder(dbConnection, dbContextOptionBuilder);
|
_shardingDbContextOptionsBuilderConfig.UseDbContextOptionsBuilder(dbConnection, dbContextOptionBuilder);
|
||||||
return dbContextOptionBuilder.Options;
|
return dbContextOptionBuilder.Options;
|
||||||
}
|
}
|
||||||
private DbContextOptions<T> CreateMonopolyDbContextOptions()
|
private DbContextOptions<T> CreateParallelDbContextOptions()
|
||||||
{
|
{
|
||||||
var dbContextOptionBuilder = CreateDbContextOptionBuilder();
|
var dbContextOptionBuilder = CreateDbContextOptionBuilder();
|
||||||
var connectionString = Database.GetDbConnection().ConnectionString;
|
var connectionString = _connectionStringManager.GetConnectionString(this);
|
||||||
_shardingDbContextOptionsBuilderConfig.UseDbContextOptionsBuilder(connectionString, dbContextOptionBuilder);
|
_shardingDbContextOptionsBuilderConfig.UseDbContextOptionsBuilder(connectionString, dbContextOptionBuilder);
|
||||||
return dbContextOptionBuilder.Options;
|
return dbContextOptionBuilder.Options;
|
||||||
}
|
}
|
||||||
|
@ -106,9 +138,9 @@ namespace ShardingCore.Sharding
|
||||||
|
|
||||||
return new ShardingDbContextOptions(_dbContextOptions, routeTail);
|
return new ShardingDbContextOptions(_dbContextOptions, routeTail);
|
||||||
}
|
}
|
||||||
private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(IRouteTail routeTail)
|
private ShardingDbContextOptions CetParallelShardingDbContextOptions(IRouteTail routeTail)
|
||||||
{
|
{
|
||||||
return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), routeTail);
|
return new ShardingDbContextOptions(CreateParallelDbContextOptions(), routeTail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,7 +165,7 @@ namespace ShardingCore.Sharding
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(routeTail));
|
return _shardingDbContextFactory.Create(ShardingDbContextType, CetParallelShardingDbContextOptions(routeTail));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +198,7 @@ namespace ShardingCore.Sharding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void UseShardingTransaction(DbTransaction transaction)
|
public void UseShardingTransaction(DbTransaction transaction)
|
||||||
{
|
{
|
||||||
_dbContextCaches.Values.ForEach(o => o.Database.UseTransaction(transaction));
|
_dbContextCaches.Values.ForEach(o => o.Database.UseTransaction(transaction));
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.Abstractions
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/7 10:29:38
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public interface IConnectionStringManager
|
||||||
|
{
|
||||||
|
Type ShardingDbContextType { get; }
|
||||||
|
string GetConnectionString(IShardingDbContext shardingDbContext);
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,7 +47,7 @@ namespace ShardingCore.Sharding.Abstractions
|
||||||
IEnumerable<DbContext> CreateExpressionDbContext<TEntity>(Expression<Func<TEntity, bool>> where)
|
IEnumerable<DbContext> CreateExpressionDbContext<TEntity>(Expression<Func<TEntity, bool>> where)
|
||||||
where TEntity : class;
|
where TEntity : class;
|
||||||
|
|
||||||
|
string GetConnectionString();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.Abstractions
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 20:27:17
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public interface IShardingReadWriteSupport
|
||||||
|
{
|
||||||
|
int ReadWritePriority { get; set; }
|
||||||
|
bool ReadWriteSupport { get; set; }
|
||||||
|
ReadConnStringGetStrategyEnum GetReadConnStringGetStrategy();
|
||||||
|
string GetWriteConnectionString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/7 10:32:26
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public class DefaultConnectionStringManager<TShardingDbContext>:IConnectionStringManager where TShardingDbContext:DbContext,IShardingDbContext
|
||||||
|
{
|
||||||
|
public Type ShardingDbContextType => typeof(TShardingDbContext);
|
||||||
|
|
||||||
|
public string GetConnectionString(IShardingDbContext shardingDbContext)
|
||||||
|
{
|
||||||
|
return shardingDbContext.GetConnectionString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ namespace ShardingCore.Sharding.PaginationConfigurations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tailComparer"></param>
|
/// <param name="tailComparer"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public PaginationOrderPropertyBuilder UseTailCompare(IComparer<string> tailComparer)
|
public PaginationOrderPropertyBuilder UseTailComparer(IComparer<string> tailComparer)
|
||||||
{
|
{
|
||||||
|
|
||||||
_paginationSequenceConfig.TailComparer= tailComparer ?? throw new ArgumentException(nameof(tailComparer));
|
_paginationSequenceConfig.TailComparer= tailComparer ?? throw new ArgumentException(nameof(tailComparer));
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
Type ShardingDbContextType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 默认读写配置优先级
|
||||||
|
/// </summary>
|
||||||
|
int ReadWritePriority { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 默认是否开启读写分离
|
||||||
|
/// </summary>
|
||||||
|
bool ReadWriteSupport { get; }
|
||||||
|
ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
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/6 13:01:59
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public interface IShardingConnectionStringResolver
|
||||||
|
{
|
||||||
|
Type ShardingDbContextType { get; }
|
||||||
|
string GetConnectionString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.ReadWriteConfigurations.Abstractions
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 16:30:44
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public interface IShardingReadWriteAccessor
|
||||||
|
{
|
||||||
|
Type ShardingDbContextType { get;}
|
||||||
|
ShardingReadWriteContext ShardingReadWriteContext { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
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/6 16:31:32
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public interface IShardingReadWriteManager
|
||||||
|
{
|
||||||
|
ShardingReadWriteContext GetCurrent<TShardingDbContext>()
|
||||||
|
where TShardingDbContext : DbContext, IShardingDbContext;
|
||||||
|
|
||||||
|
ShardingReadWriteContext GetCurrent(Type shardingDbContextType);
|
||||||
|
|
||||||
|
ShardingReadWriteScope<TShardingDbContext> CreateScope<TShardingDbContext>()
|
||||||
|
where TShardingDbContext : DbContext, IShardingDbContext;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.ReadWriteConfigurations
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 14:39:23
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public class LoopShardingConnectionStringResolver<TShardingDbContext> : IShardingConnectionStringResolver
|
||||||
|
{
|
||||||
|
public Type ShardingDbContextType => typeof(TShardingDbContext);
|
||||||
|
|
||||||
|
private readonly string[] _connectionStrings;
|
||||||
|
private readonly int _length;
|
||||||
|
private long _seed = 0;
|
||||||
|
public LoopShardingConnectionStringResolver(IEnumerable<string> connectionStrings)
|
||||||
|
{
|
||||||
|
_connectionStrings = connectionStrings.ToArray();
|
||||||
|
_length = _connectionStrings.Length;
|
||||||
|
}
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _seed);
|
||||||
|
var next = (int)(_seed % _length);
|
||||||
|
if (next < 0)
|
||||||
|
return _connectionStrings[Math.Abs(next)];
|
||||||
|
return _connectionStrings[next];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using ShardingCore.Helpers;
|
||||||
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.ReadWriteConfigurations
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 14:22:55
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public class RandomShardingConnectionStringResolver<TShardingDbContext> :IShardingConnectionStringResolver
|
||||||
|
{
|
||||||
|
public Type ShardingDbContextType => typeof(TShardingDbContext);
|
||||||
|
|
||||||
|
private readonly string[] _connectionStrings;
|
||||||
|
private readonly int _length;
|
||||||
|
public RandomShardingConnectionStringResolver(IEnumerable<string> connectionStrings)
|
||||||
|
{
|
||||||
|
_connectionStrings = connectionStrings.ToArray();
|
||||||
|
_length = _connectionStrings.Length;
|
||||||
|
}
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
var next = RandomHelper.Next(0, _length);
|
||||||
|
return _connectionStrings[next];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.ReadWriteConfigurations
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 13:08:31
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public enum ReadStrategyEnum
|
||||||
|
{
|
||||||
|
Random=1,
|
||||||
|
Loop=2,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ReadConnStringGetStrategyEnum
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 每次都是最新的
|
||||||
|
/// </summary>
|
||||||
|
LatestEveryTime,
|
||||||
|
/// <summary>
|
||||||
|
/// 已dbcontext作为缓存条件每次都是第一次获取的
|
||||||
|
/// </summary>
|
||||||
|
LatestFirstTime
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
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 10:37:28
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public class ReadWriteConnectionStringManager<TShardingDbContext> : IConnectionStringManager where TShardingDbContext : DbContext, IShardingDbContext
|
||||||
|
{
|
||||||
|
private readonly IShardingReadWriteManager _shardingReadWriteManager;
|
||||||
|
public Type ShardingDbContextType => typeof(TShardingDbContext);
|
||||||
|
private IShardingConnectionStringResolver _shardingConnectionStringResolver;
|
||||||
|
private string _cacheConnectionString;
|
||||||
|
|
||||||
|
|
||||||
|
public ReadWriteConnectionStringManager(IShardingReadWriteManager shardingReadWriteManager, IEnumerable<IShardingConnectionStringResolver> shardingConnectionStringResolvers)
|
||||||
|
{
|
||||||
|
_shardingReadWriteManager = shardingReadWriteManager;
|
||||||
|
_shardingConnectionStringResolver = shardingConnectionStringResolvers.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType) ?? throw new ArgumentNullException($"{ShardingDbContextType.FullName}:{nameof(shardingConnectionStringResolvers)}");
|
||||||
|
}
|
||||||
|
public string GetConnectionString(IShardingDbContext shardingDbContext)
|
||||||
|
{
|
||||||
|
if (!(shardingDbContext is IShardingReadWriteSupport shardingReadWriteSupport))
|
||||||
|
{
|
||||||
|
return shardingDbContext.GetConnectionString();
|
||||||
|
}
|
||||||
|
var shardingReadWriteContext = _shardingReadWriteManager.GetCurrent(ShardingDbContextType);
|
||||||
|
var support = shardingReadWriteSupport.ReadWriteSupport;
|
||||||
|
if (shardingReadWriteContext != null)
|
||||||
|
{
|
||||||
|
support = (shardingReadWriteSupport.ReadWritePriority >= shardingReadWriteContext.DefaultPriority)
|
||||||
|
? shardingReadWriteSupport.ReadWriteSupport
|
||||||
|
: shardingReadWriteContext.DefaultReadEnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (support)
|
||||||
|
{
|
||||||
|
return GetReadConnectionString0(shardingReadWriteSupport);
|
||||||
|
}
|
||||||
|
return shardingReadWriteSupport.GetWriteConnectionString();
|
||||||
|
}
|
||||||
|
private string GetReadConnectionString0(IShardingReadWriteSupport shardingReadWriteSupport)
|
||||||
|
{
|
||||||
|
var readConnStringGetStrategy = shardingReadWriteSupport.GetReadConnStringGetStrategy();
|
||||||
|
if (readConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestFirstTime)
|
||||||
|
{
|
||||||
|
if (_cacheConnectionString == null)
|
||||||
|
_cacheConnectionString = _shardingConnectionStringResolver.GetConnectionString();
|
||||||
|
return _cacheConnectionString;
|
||||||
|
}
|
||||||
|
else if (readConnStringGetStrategy == ReadConnStringGetStrategyEnum.LatestEveryTime)
|
||||||
|
{
|
||||||
|
return _shardingConnectionStringResolver.GetConnectionString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"ReadWriteConnectionStringManager:{readConnStringGetStrategy}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ReadWriteOptions<TShardingDbContext> : IReadWriteOptions
|
||||||
|
where TShardingDbContext : DbContext, IShardingDbContext
|
||||||
|
{
|
||||||
|
public ReadWriteOptions(int readWritePriority, bool readWriteSupport, ReadConnStringGetStrategyEnum readConnStringGetStrategy)
|
||||||
|
{
|
||||||
|
ReadWritePriority = readWritePriority;
|
||||||
|
ReadWriteSupport = readWriteSupport;
|
||||||
|
ReadConnStringGetStrategy = readConnStringGetStrategy;
|
||||||
|
}
|
||||||
|
public Type ShardingDbContextType => typeof(TShardingDbContext);
|
||||||
|
/// <summary>
|
||||||
|
/// 默认读写配置优先级
|
||||||
|
/// </summary>
|
||||||
|
public int ReadWritePriority { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 默认是否开启读写分离
|
||||||
|
/// </summary>
|
||||||
|
public bool ReadWriteSupport { get; }
|
||||||
|
public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.ReadWriteConfigurations
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 16:54:23
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public class ShardingReadWriteAccessor<TShardingDbContext>:IShardingReadWriteAccessor where TShardingDbContext:DbContext,IShardingDbContext
|
||||||
|
{
|
||||||
|
private static AsyncLocal<ShardingReadWriteContext> _shardingReadWriteContext = new AsyncLocal<ShardingReadWriteContext>();
|
||||||
|
|
||||||
|
public Type ShardingDbContextType => typeof(TShardingDbContext);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public ShardingReadWriteContext ShardingReadWriteContext
|
||||||
|
{
|
||||||
|
get => _shardingReadWriteContext.Value;
|
||||||
|
set => _shardingReadWriteContext.Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.ReadWriteConfigurations
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 16:52:29
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public class ShardingReadWriteContext
|
||||||
|
{
|
||||||
|
public bool DefaultReadEnable { get; set; }
|
||||||
|
public int DefaultPriority { get; set; }
|
||||||
|
|
||||||
|
private ShardingReadWriteContext()
|
||||||
|
{
|
||||||
|
DefaultReadEnable = false;
|
||||||
|
DefaultPriority = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ShardingReadWriteContext Create()
|
||||||
|
{
|
||||||
|
return new ShardingReadWriteContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using ShardingCore.Extensions;
|
||||||
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||||
|
|
||||||
|
namespace ShardingCore.Sharding.ReadWriteConfigurations
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/9/6 21:02:56
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public class ShardingReadWriteManager:IShardingReadWriteManager
|
||||||
|
{
|
||||||
|
private readonly ConcurrentDictionary<Type, IShardingReadWriteAccessor> _shardingReadWriteAccessors;
|
||||||
|
|
||||||
|
public ShardingReadWriteContext GetCurrent<TShardingDbContext>() where TShardingDbContext : DbContext, IShardingDbContext
|
||||||
|
{
|
||||||
|
return GetCurrent(typeof(TShardingDbContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShardingReadWriteContext GetCurrent(Type shardingDbContextType)
|
||||||
|
{
|
||||||
|
if (!shardingDbContextType.IsShardingDbContext())
|
||||||
|
throw new InvalidOperationException(shardingDbContextType.FullName);
|
||||||
|
|
||||||
|
if (_shardingReadWriteAccessors.TryGetValue(shardingDbContextType, out var accessor))
|
||||||
|
return accessor.ShardingReadWriteContext;
|
||||||
|
throw new InvalidOperationException(shardingDbContextType.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShardingReadWriteManager(IEnumerable<IShardingReadWriteAccessor> shardingReadWriteAccessors)
|
||||||
|
{
|
||||||
|
|
||||||
|
_shardingReadWriteAccessors = new ConcurrentDictionary<Type,IShardingReadWriteAccessor>(shardingReadWriteAccessors.ToDictionary(o => o.ShardingDbContextType, o => o));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShardingReadWriteScope<TShardingDbContext> CreateScope<TShardingDbContext>() where TShardingDbContext : DbContext, IShardingDbContext
|
||||||
|
{
|
||||||
|
var shardingPageScope = new ShardingReadWriteScope<TShardingDbContext>(_shardingReadWriteAccessors.Values);
|
||||||
|
shardingPageScope.ShardingReadWriteAccessor.ShardingReadWriteContext = ShardingReadWriteContext.Create();
|
||||||
|
return shardingPageScope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
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/6 20:58:57
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
public class ShardingReadWriteScope<TShardingDbContext>:IDisposable
|
||||||
|
where TShardingDbContext : DbContext, IShardingDbContext
|
||||||
|
{
|
||||||
|
public IShardingReadWriteAccessor ShardingReadWriteAccessor { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="shardingReadWriteAccessors"></param>
|
||||||
|
public ShardingReadWriteScope(IEnumerable<IShardingReadWriteAccessor> shardingReadWriteAccessors)
|
||||||
|
{
|
||||||
|
ShardingReadWriteAccessor = shardingReadWriteAccessors.FirstOrDefault(o=>o.ShardingDbContextType==typeof(TShardingDbContext))??throw new ArgumentNullException(nameof(shardingReadWriteAccessors));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 回收
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
ShardingReadWriteAccessor.ShardingReadWriteContext = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ using ShardingCore.Core.VirtualRoutes.TableRoutes;
|
||||||
using ShardingCore.EFCores;
|
using ShardingCore.EFCores;
|
||||||
using ShardingCore.Sharding;
|
using ShardingCore.Sharding;
|
||||||
using ShardingCore.Sharding.Abstractions;
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||||
|
|
||||||
namespace ShardingCore
|
namespace ShardingCore
|
||||||
{
|
{
|
||||||
|
@ -25,13 +26,13 @@ namespace ShardingCore
|
||||||
{
|
{
|
||||||
private readonly Dictionary<Type, Type> _virtualRoutes = new Dictionary<Type, Type>();
|
private readonly Dictionary<Type, Type> _virtualRoutes = new Dictionary<Type, Type>();
|
||||||
|
|
||||||
public Action<DbConnection, DbContextOptionsBuilder> SameConnectionConfigure { get; set; }
|
public Action<DbConnection, DbContextOptionsBuilder> SameConnectionConfigure { get;private set; }
|
||||||
public Action<string,DbContextOptionsBuilder> DefaultQueryConfigure { get; set; }
|
public Action<string,DbContextOptionsBuilder> DefaultQueryConfigure { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置数据库分表查询和保存时的DbContext创建方式
|
/// 配置数据库分表查询和保存时的DbContext创建方式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sameConnectionConfigure">DbConnection下如何配置因为不同的DbContext支持事务需要使用同一个DbConnection</param>
|
/// <param name="sameConnectionConfigure">DbConnection下如何配置因为不同的DbContext支持事务需要使用同一个DbConnection</param>
|
||||||
/// <param name="defaultBuilderConfigure">默认查询DbContext创建的配置</param>
|
/// <param name="defaultQueryConfigure">默认查询DbContext创建的配置</param>
|
||||||
|
|
||||||
public void UseShardingOptionsBuilder(Action<DbConnection, DbContextOptionsBuilder> sameConnectionConfigure, Action<string,DbContextOptionsBuilder> defaultQueryConfigure = null)
|
public void UseShardingOptionsBuilder(Action<DbConnection, DbContextOptionsBuilder> sameConnectionConfigure, Action<string,DbContextOptionsBuilder> defaultQueryConfigure = null)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +40,30 @@ namespace ShardingCore
|
||||||
DefaultQueryConfigure = defaultQueryConfigure ?? throw new ArgumentNullException(nameof(defaultQueryConfigure));
|
DefaultQueryConfigure = defaultQueryConfigure ?? throw new ArgumentNullException(nameof(defaultQueryConfigure));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool UseReadWrite => ReadConnStringConfigure != null;
|
||||||
|
public Func<IServiceProvider, IEnumerable<string>> ReadConnStringConfigure { get; private set; }
|
||||||
|
public ReadStrategyEnum ReadStrategyEnum { get; private set; }
|
||||||
|
public bool ReadWriteDefaultEnable { get; private set; }
|
||||||
|
public int ReadWriteDefaultPriority { get; private set; }
|
||||||
|
public ReadConnStringGetStrategyEnum ReadConnStringGetStrategy { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用读写分离配置
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="readConnStringConfigure"></param>
|
||||||
|
/// <param name="readStrategyEnum"></param>
|
||||||
|
/// <param name="defaultEnable">考虑到很多时候读写分离的延迟需要马上用到写入的数据所以默认关闭需要的话自己开启或者通过IShardingReadWriteManager,false表示默认不走读写分离除非你自己开启,true表示默认走读写分离除非你禁用,</param>
|
||||||
|
/// <param name="defaultPriority">IShardingReadWriteManager.CreateScope()会判断dbcontext的priority然后判断是否启用readwrite</param>
|
||||||
|
/// <param name="readConnStringGetStrategy">读写分离可能会造成每次查询不一样甚至分表后的分页会有错位问题,因为他不是一个原子操作,所以如果整个请求为一次读写切换大多数更加合适</param>
|
||||||
|
public void UseReadWriteConfiguration(Func<IServiceProvider, IEnumerable<string>> readConnStringConfigure, ReadStrategyEnum readStrategyEnum,bool defaultEnable=false,int defaultPriority=10,ReadConnStringGetStrategyEnum readConnStringGetStrategy= ReadConnStringGetStrategyEnum.LatestFirstTime)
|
||||||
|
{
|
||||||
|
ReadConnStringConfigure = readConnStringConfigure ?? throw new ArgumentNullException(nameof(readConnStringConfigure));
|
||||||
|
ReadStrategyEnum = readStrategyEnum;
|
||||||
|
ReadWriteDefaultEnable = defaultEnable;
|
||||||
|
ReadWriteDefaultPriority = defaultPriority;
|
||||||
|
ReadConnStringGetStrategy = readConnStringGetStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Type ShardingDbContextType => typeof(TShardingDbContext);
|
public Type ShardingDbContextType => typeof(TShardingDbContext);
|
||||||
public Type ActualDbContextType => typeof(TActualDbContext);
|
public Type ActualDbContextType => typeof(TActualDbContext);
|
||||||
|
|
Loading…
Reference in New Issue