Merge branch 'sharding-6'

# Conflicts:
#	samples/Sample.MySql/Startup.cs
#	src/ShardingCore/EFCores/OptionsExtensions/ShardingWrapOptionsExtension.cs
#	src/ShardingCore/ShardingCoreExtension.cs
This commit is contained in:
xuejiaming 2022-07-02 16:50:33 +08:00
commit 8795cca4f4
226 changed files with 3277 additions and 4304 deletions

View File

@ -1,73 +1,73 @@
using System.Data.Common;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.DynamicDataSources;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
using ShardingCore.TableExists.Abstractions;
namespace Sample.MultiConfig.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class CommonController : ControllerBase
{
private readonly IVirtualDataSourceManager<MultiConfigDbContext> _virtualDataSourceManager;
public CommonController(IVirtualDataSourceManager<MultiConfigDbContext> virtualDataSourceManager)
{
_virtualDataSourceManager = virtualDataSourceManager;
}
public async Task<IActionResult> DynamicAdd(string configId)
{
var flag = DynamicDataSourceHelper.DynamicAppendVirtualDataSource(new MySqlConfigurationParam(configId));
return Ok(flag?"成功":"失败");
}
}
public class MySqlConfigurationParam : AbstractVirtualDataSourceConfigurationParams<MultiConfigDbContext>
{
public override string ConfigId { get; }
public override int Priority { get; }
public override string DefaultDataSourceName { get; }
public override string DefaultConnectionString { get; }
public override IDictionary<string, ReadNode[]> ReadWriteNodeSeparationConfigs { get; }
public override ReadStrategyEnum? ReadStrategy { get; }
public override bool? ReadWriteDefaultEnable { get; }
public override int? ReadWriteDefaultPriority { get; }
public override ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; }
public MySqlConfigurationParam(string configId)
{
ConfigId = configId;
DefaultDataSourceName = "ds0";
DefaultConnectionString = $"server=127.0.0.1;port=3306;database=MultiConfigSharding{configId};userid=root;password=L6yBtV6qNENrwBy7;";
}
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
DbContextOptionsBuilder dbContextOptionsBuilder)
{
dbContextOptionsBuilder.UseMySql(connectionString,new MySqlServerVersion(new Version()));
return dbContextOptionsBuilder;
}
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection,
DbContextOptionsBuilder dbContextOptionsBuilder)
{
dbContextOptionsBuilder.UseMySql(dbConnection, new MySqlServerVersion(new Version()));
return dbContextOptionsBuilder;
}
public override void UseShellDbContextOptionBuilder(DbContextOptionsBuilder dbContextOptionsBuilder)
{
}
public override void UseExecutorDbContextOptionBuilder(DbContextOptionsBuilder dbContextOptionsBuilder)
{
}
}
}
// using System.Data.Common;
// using Microsoft.AspNetCore.Mvc;
// using Microsoft.EntityFrameworkCore;
// using ShardingCore.Core;
// using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
// using ShardingCore.DynamicDataSources;
// using ShardingCore.Sharding.ReadWriteConfigurations;
// using ShardingCore.Sharding.ShardingComparision.Abstractions;
// using ShardingCore.TableExists.Abstractions;
//
// namespace Sample.MultiConfig.Controllers
// {
// [ApiController]
// [Route("[controller]/[action]")]
// public class CommonController : ControllerBase
// {
// private readonly IVirtualDataSourceManager<MultiConfigDbContext> _virtualDataSourceManager;
//
// public CommonController(IVirtualDataSourceManager<MultiConfigDbContext> virtualDataSourceManager)
// {
// _virtualDataSourceManager = virtualDataSourceManager;
// }
// public async Task<IActionResult> DynamicAdd(string configId)
// {
// var flag = DynamicDataSourceHelper.DynamicAppendVirtualDataSource(new MySqlConfigurationParam(configId));
// return Ok(flag?"成功":"失败");
// }
// }
//
// public class MySqlConfigurationParam : AbstractVirtualDataSourceConfigurationParams<MultiConfigDbContext>
// {
// public override string ConfigId { get; }
// public override int Priority { get; }
// public override string DefaultDataSourceName { get; }
// public override string DefaultConnectionString { get; }
// public override IDictionary<string, ReadNode[]> ReadWriteNodeSeparationConfigs { get; }
// public override ReadStrategyEnum? ReadStrategy { get; }
// public override bool? ReadWriteDefaultEnable { get; }
// public override int? ReadWriteDefaultPriority { get; }
// public override ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; }
//
// public MySqlConfigurationParam(string configId)
// {
// ConfigId = configId;
// DefaultDataSourceName = "ds0";
// DefaultConnectionString = $"server=127.0.0.1;port=3306;database=MultiConfigSharding{configId};userid=root;password=L6yBtV6qNENrwBy7;";
// }
//
// public override DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
// DbContextOptionsBuilder dbContextOptionsBuilder)
// {
// dbContextOptionsBuilder.UseMySql(connectionString,new MySqlServerVersion(new Version()));
// return dbContextOptionsBuilder;
// }
//
// public override DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection,
// DbContextOptionsBuilder dbContextOptionsBuilder)
// {
// dbContextOptionsBuilder.UseMySql(dbConnection, new MySqlServerVersion(new Version()));
// return dbContextOptionsBuilder;
// }
//
// public override void UseShellDbContextOptionBuilder(DbContextOptionsBuilder dbContextOptionsBuilder)
// {
//
// }
//
// public override void UseExecutorDbContextOptionBuilder(DbContextOptionsBuilder dbContextOptionsBuilder)
// {
//
// }
// }
// }

View File

@ -1,37 +1,37 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Sample.MultiConfig.Domain.Entities;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
namespace Sample.MultiConfig.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class TestController:ControllerBase
{
private readonly MultiConfigDbContext _multiConfigDbContext;
private readonly IVirtualTableManager<MultiConfigDbContext> _virtualTableManager;
public TestController(MultiConfigDbContext multiConfigDbContext,IVirtualTableManager<MultiConfigDbContext> virtualTableManager)
{
_multiConfigDbContext = multiConfigDbContext;
_virtualTableManager = virtualTableManager;
}
public async Task<IActionResult> Add()
{
var order = new Order();
order.Id = Guid.NewGuid().ToString("n");
order.Name = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
order.CreateTime=DateTime.Now;
await _multiConfigDbContext.AddAsync(order);
await _multiConfigDbContext.SaveChangesAsync();
return Ok();
}
public async Task<IActionResult> Query()
{
var listAsync = await _multiConfigDbContext.Set<Order>().ToListAsync();
return Ok(listAsync);
}
}
}
// using Microsoft.AspNetCore.Mvc;
// using Microsoft.EntityFrameworkCore;
// using Sample.MultiConfig.Domain.Entities;
// using ShardingCore.Core.VirtualDatabase.VirtualTables;
//
// namespace Sample.MultiConfig.Controllers
// {
// [ApiController]
// [Route("[controller]/[action]")]
// public class TestController:ControllerBase
// {
// private readonly MultiConfigDbContext _multiConfigDbContext;
// private readonly IVirtualTableManager<MultiConfigDbContext> _virtualTableManager;
//
// public TestController(MultiConfigDbContext multiConfigDbContext,IVirtualTableManager<MultiConfigDbContext> virtualTableManager)
// {
// _multiConfigDbContext = multiConfigDbContext;
// _virtualTableManager = virtualTableManager;
// }
// public async Task<IActionResult> Add()
// {
// var order = new Order();
// order.Id = Guid.NewGuid().ToString("n");
// order.Name = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
// order.CreateTime=DateTime.Now;
// await _multiConfigDbContext.AddAsync(order);
// await _multiConfigDbContext.SaveChangesAsync();
// return Ok();
// }
// public async Task<IActionResult> Query()
// {
// var listAsync = await _multiConfigDbContext.Set<Order>().ToListAsync();
// return Ok(listAsync);
// }
//
// }
// }

View File

@ -1,47 +1,47 @@
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
namespace Sample.MultiConfig.Middlewares
{
public class TenantSelectMiddleware
{
private readonly RequestDelegate _next;
private readonly IVirtualDataSourceManager<MultiConfigDbContext> _virtualDataSourceManager;
public TenantSelectMiddleware(RequestDelegate next, IVirtualDataSourceManager<MultiConfigDbContext> virtualDataSourceManager)
{
_next = next;
_virtualDataSourceManager = virtualDataSourceManager;
}
/// <summary>
/// 1.中间件的方法必须叫Invoke且为public非static。
/// 2.Invoke方法第一个参数必须是HttpContext类型。
/// 3.Invoke方法必须返回Task。
/// 4.Invoke方法可以有多个参数除HttpContext外其它参数会尝试从依赖注入容器中获取。
/// 5.Invoke方法不能有重载。
/// </summary>
/// Author : Napoleon
/// Created : 2020/1/30 21:30
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.ToString().StartsWith("/test", StringComparison.CurrentCultureIgnoreCase))
{
if (!context.Request.Headers.ContainsKey("TenantId") || !_virtualDataSourceManager.ContansConfigId(context.Request.Headers["TenantId"]))
{
context.Response.StatusCode = 403; //UnAuthorized
await context.Response.WriteAsync("403 not found TenantId");
return;
}
using (_virtualDataSourceManager.CreateScope(context.Request.Headers["TenantId"]))
{
await _next(context);
}
}
else
{
await _next(context);
}
}
}
}
// using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
//
// namespace Sample.MultiConfig.Middlewares
// {
// public class TenantSelectMiddleware
// {
// private readonly RequestDelegate _next;
// private readonly IVirtualDataSourceManager<MultiConfigDbContext> _virtualDataSourceManager;
//
// public TenantSelectMiddleware(RequestDelegate next, IVirtualDataSourceManager<MultiConfigDbContext> virtualDataSourceManager)
// {
// _next = next;
// _virtualDataSourceManager = virtualDataSourceManager;
// }
//
// /// <summary>
// /// 1.中间件的方法必须叫Invoke且为public非static。
// /// 2.Invoke方法第一个参数必须是HttpContext类型。
// /// 3.Invoke方法必须返回Task。
// /// 4.Invoke方法可以有多个参数除HttpContext外其它参数会尝试从依赖注入容器中获取。
// /// 5.Invoke方法不能有重载。
// /// </summary>
// /// Author : Napoleon
// /// Created : 2020/1/30 21:30
// public async Task Invoke(HttpContext context)
// {
// if (context.Request.Path.ToString().StartsWith("/test", StringComparison.CurrentCultureIgnoreCase))
// {
// if (!context.Request.Headers.ContainsKey("TenantId") || !_virtualDataSourceManager.ContansConfigId(context.Request.Headers["TenantId"]))
// {
// context.Response.StatusCode = 403; //UnAuthorized
// await context.Response.WriteAsync("403 not found TenantId");
// return;
// }
//
// using (_virtualDataSourceManager.CreateScope(context.Request.Headers["TenantId"]))
// {
// await _next(context);
// }
// }
// else
// {
// await _next(context);
// }
// }
// }
// }

View File

@ -1,64 +1,60 @@
using Microsoft.EntityFrameworkCore;
using Sample.MultiConfig;
using Sample.MultiConfig.Middlewares;
using ShardingCore;
using ShardingCore.Bootstrappers;
using ShardingCore.TableExists;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
ILoggerFactory efLogger = LoggerFactory.Create(builder =>
{
builder.AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole();
});
builder.Services.AddControllers();
builder.Services.AddShardingDbContext<MultiConfigDbContext>()
.AddEntityConfig(op =>
{
op.CreateShardingTableOnStart = true;
op.EnsureCreatedWithOutShardingTable = true;
op.AddShardingTableRoute<OrderIdModVirtualTableRoute>();
})
.AddConfig(op =>
{
op.ConfigId = "c1";
op.UseShardingQuery((conStr, b) =>
{
b.UseSqlServer(conStr).UseLoggerFactory(efLogger);
});
op.UseShardingTransaction((conn, b) =>
{
b.UseSqlServer(conn).UseLoggerFactory(efLogger);
});
op.AddDefaultDataSource("ds0",
"Data Source=localhost;Initial Catalog=MultiConfigSharding;Integrated Security=True;");
op.ReplaceTableEnsureManager(sp => new SqlServerTableEnsureManager<MultiConfigDbContext>());
})
.AddConfig(op =>
{
op.ConfigId = "c2";
op.UseShardingQuery((conStr, b) =>
{
b.UseMySql(conStr, new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger);
});
op.UseShardingTransaction((conn, b) =>
{
b.UseMySql(conn, new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger);
});
op.AddDefaultDataSource("ds0",
"server=127.0.0.1;port=3306;database=MultiConfigSharding;userid=root;password=L6yBtV6qNENrwBy7;");
op.ReplaceTableEnsureManager(sp => new MySqlTableEnsureManager<MultiConfigDbContext>());
}).EnsureMultiConfig();
//
// // Add services to the container.
//
// ILoggerFactory efLogger = LoggerFactory.Create(builder =>
// {
// builder.AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole();
// });
// builder.Services.AddControllers();
// builder.Services.AddShardingDbContext<MultiConfigDbContext>()
// .AddEntityConfig(op =>
// {
// op.AddShardingTableRoute<OrderIdModVirtualTableRoute>();
// })
// .AddConfig(op =>
// {
// // op.ConfigId = "c1";
// op.UseShardingQuery((conStr, b) =>
// {
// b.UseSqlServer(conStr).UseLoggerFactory(efLogger);
// });
// op.UseShardingTransaction((conn, b) =>
// {
// b.UseSqlServer(conn).UseLoggerFactory(efLogger);
// });
// op.AddDefaultDataSource("ds0",
// "Data Source=localhost;Initial Catalog=MultiConfigSharding;Integrated Security=True;");
// // op.ReplaceTableEnsureManager(sp => new SqlServerTableEnsureManager<MultiConfigDbContext>());
// })
// .AddConfig(op =>
// {
// op.ConfigId = "c2";
// op.UseShardingQuery((conStr, b) =>
// {
// b.UseMySql(conStr, new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger);
// });
// op.UseShardingTransaction((conn, b) =>
// {
// b.UseMySql(conn, new MySqlServerVersion(new Version())).UseLoggerFactory(efLogger);
// });
// op.AddDefaultDataSource("ds0",
// "server=127.0.0.1;port=3306;database=MultiConfigSharding;userid=root;password=L6yBtV6qNENrwBy7;");
// op.ReplaceTableEnsureManager(sp => new MySqlTableEnsureManager<MultiConfigDbContext>());
// }).EnsureMultiConfig();
//
var app = builder.Build();
// Configure the HTTP request pipeline.
app.Services.GetRequiredService<IShardingBootstrapper>().Start();
//
// // Configure the HTTP request pipeline.
// app.Services.GetRequiredService<IShardingBootstrapper>().Start();
app.UseAuthorization();
app.UseMiddleware<TenantSelectMiddleware>();
// app.UseMiddleware<TenantSelectMiddleware>();
//
app.MapControllers();
//
app.Run();

View File

@ -1,74 +1,63 @@
// using Microsoft.AspNetCore.Mvc;
// using Microsoft.Extensions.Logging;
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Threading.Tasks;
// using Microsoft.EntityFrameworkCore;
// using Sample.MySql.DbContexts;
// using Sample.MySql.Domain.Entities;
// using ShardingCore.Core.PhysicTables;
// using ShardingCore.Core.VirtualTables;
// using ShardingCore.DbContexts.VirtualDbContexts;
// using ShardingCore.Extensions;
// using ShardingCore.TableCreator;
//
// namespace Sample.MySql.Controllers
// {
// [ApiController]
// [Route("[controller]/[action]")]
// public class WeatherForecastController : ControllerBase
// {
//
// private readonly DefaultTableDbContext _defaultTableDbContext;
// private readonly IVirtualTableManager _virtualTableManager;
// private readonly IShardingTableCreator _tableCreator;
//
// public WeatherForecastController(DefaultTableDbContext defaultTableDbContext,IVirtualTableManager virtualTableManager, IShardingTableCreator tableCreator)
// {
// _defaultTableDbContext = defaultTableDbContext;
// _virtualTableManager = virtualTableManager;
// _tableCreator = tableCreator;
// }
//
// [HttpGet]
// public async Task<IActionResult> Get()
// {
// var taleAllTails = _virtualTableManager.GetVirtualTable(typeof(SysUserLogByMonth)).GetTableAllTails();
//
//
// var result = await _defaultTableDbContext.Set<SysTest>().AnyAsync();
// var result1 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "2" || o.Id == "3").ToShardingListAsync();
// var result2 = await _defaultTableDbContext.Set<SysUserLogByMonth>().Skip(1).Take(10).ToShardingListAsync();
// var shardingFirstOrDefaultAsync = await _defaultTableDbContext.Set<SysUserLogByMonth>().ShardingFirstOrDefaultAsync();
// var shardingCountAsync = await _defaultTableDbContext.Set<SysUserMod>().ShardingCountAsync();
// var shardingCountAsyn2c = _defaultTableDbContext.Set<SysUserLogByMonth>().ShardingCount();
//
// return Ok(result1);
// }
// [HttpGet]
// public async Task<IActionResult> Get1()
// {
// var allVirtualTables = _virtualTableManager.GetAllVirtualTables();
// foreach (var virtualTable in allVirtualTables)
// {
// if (virtualTable.EntityType == typeof(SysUserLogByMonth))
// {
// var now = DateTime.Now.Date.AddMonths(2);
// var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now);
// try
// {
// _virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, tail));
// _tableCreator.CreateTable<SysUserLogByMonth>(tail);
// }
// catch (Exception e)
// {
// //ignore
// Console.WriteLine(e);
// }
// }
// }
// return Ok();
// }
// }
// }
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Sample.MySql.DbContexts;
using Sample.MySql.Domain.Entities;
using ShardingCore.TableCreator;
namespace Sample.MySql.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class WeatherForecastController : ControllerBase
{
private readonly DefaultShardingDbContext _defaultTableDbContext;
public WeatherForecastController(DefaultShardingDbContext defaultTableDbContext)
{
_defaultTableDbContext = defaultTableDbContext;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var result = await _defaultTableDbContext.Set<SysTest>().AnyAsync();
var result1 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "2" || o.Id == "3").ToListAsync();
var result2 = await _defaultTableDbContext.Set<SysUserLogByMonth>().Skip(1).Take(10).ToListAsync();
var shardingFirstOrDefaultAsync = await _defaultTableDbContext.Set<SysUserLogByMonth>().ToListAsync();
var shardingCountAsync = await _defaultTableDbContext.Set<SysUserMod>().CountAsync();
var shardingCountAsyn2c = _defaultTableDbContext.Set<SysUserLogByMonth>().Count();
return Ok(result1);
}
// [HttpGet]
// public async Task<IActionResult> Get1()
// {
// var allVirtualTables = _virtualTableManager.GetAllVirtualTables();
// foreach (var virtualTable in allVirtualTables)
// {
// if (virtualTable.EntityType == typeof(SysUserLogByMonth))
// {
// var now = DateTime.Now.Date.AddMonths(2);
// var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now);
// try
// {
// _virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, tail));
// _tableCreator.CreateTable<SysUserLogByMonth>(tail);
// }
// catch (Exception e)
// {
// //ignore
// Console.WriteLine(e);
// }
// }
// }
// return Ok();
// }
}
}

View File

@ -17,13 +17,6 @@ namespace Sample.MySql
*/
public static class DIExtension
{
public static IApplicationBuilder UseShardingCore(this IApplicationBuilder app)
{
var shardingBootstrapper = app.ApplicationServices.GetRequiredService<IShardingBootstrapper>();
shardingBootstrapper.Start();
return app;
}
public static void DbSeed(this IApplicationBuilder app)
{
using (var scope=app.ApplicationServices.CreateScope())

View File

@ -9,7 +9,6 @@ namespace Sample.MySql.Domain.Entities
public class SysUserLogByMonth
{
public string Id { get; set; }
[ShardingTableKey]
public DateTime Time { get; set; }
}
}

View File

@ -13,7 +13,6 @@ namespace Sample.MySql.Domain.Entities
/// <summary>
/// 用户Id用于分表
/// </summary>
[ShardingTableKey]
public string Id { get; set; }
/// <summary>
/// 用户名称

View File

@ -7,6 +7,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.1" />
</ItemGroup>

View File

@ -22,7 +22,7 @@ namespace Sample.MySql.Shardings
public override void Configure(EntityMetadataTableBuilder<SysUserLogByMonth> builder)
{
builder.ShardingProperty(o => o.Time);
}
}
}

View File

@ -18,7 +18,8 @@ namespace Sample.MySql.Shardings
public override void Configure(EntityMetadataTableBuilder<SysUserMod> builder)
{
builder.ShardingProperty(o => o.Id);
}
}
}

View File

@ -1,18 +1,12 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MySqlConnector;
using Sample.MySql.DbContexts;
using Sample.MySql.Shardings;
using ShardingCore;
using ShardingCore.EFCores.OptionsExtensions;
using ShardingCore.Helpers;
using ShardingCore.TableExists;
using ShardingCore.Bootstrappers;
using ShardingCore.Core;
using ShardingCore.Core.RuntimeContexts;
using ShardingCore.Extensions;
namespace Sample.MySql
{
@ -43,67 +37,80 @@ namespace Sample.MySql
// op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
// op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
// });
// services.AddSingleton<IShardingRuntimeContext, ShardingRuntimeContext>();
services.AddShardingDbContext<DefaultShardingDbContext>()
.AddEntityConfig(o =>
{
o.CreateDataBaseOnlyOnStart = true;
o.CreateShardingTableOnStart = true;
o.EnsureCreatedWithOutShardingTable = true;
o.IgnoreCreateTableError = true;
o.AddShardingTableRoute<SysUserLogByMonthRoute>();
o.AddShardingTableRoute<SysUserModVirtualTableRoute>();
o.AddShardingDataSourceRoute<SysUserModVirtualDataSourceRoute>();
o.UseShardingQuery((conStr, builder) =>
{
builder.UseMySql(conStr, new MySqlServerVersion(new Version())
,b=>b.EnableRetryOnFailure()
)
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(efLogger);
//builder.UseMySql(conStr, new MySqlServerVersion(new Version()));
});
o.UseShardingTransaction((connection, builder) =>
{
builder.UseMySql(connection, new MySqlServerVersion(new Version())
,b=>b.EnableRetryOnFailure()
)
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(efLogger);
});
})
.AddConfig(op =>
{
op.ConfigId = "c0";
op.AddDefaultDataSource("ds0",
"server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;");
//op.AddDefaultDataSource("ds0", "server=127.0.0.1;port=3306;database=db2;userid=root;password=L6yBtV6qNENrwBy7;")
op.ReplaceTableEnsureManager(sp=>new MySqlTableEnsureManager<DefaultShardingDbContext>());
}).EnsureConfig();
services.AddSingleton<IShardingRuntimeContext>(sp =>
{
Stopwatch stopwatch=Stopwatch.StartNew();
var shardingRuntimeContext = new ShardingRuntimeBuilder<DefaultShardingDbContext>()
.UseRouteConfig(o =>
{
o.AddShardingTableRoute<SysUserLogByMonthRoute>();
o.AddShardingTableRoute<SysUserModVirtualTableRoute>();
// o.AddShardingDataSourceRoute<SysUserModVirtualDataSourceRoute>();
}).UseConfig(o =>
{
o.UseShardingQuery((conStr,builder)=>
{
builder.UseMySql(conStr, new MySqlServerVersion(new Version())).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(efLogger);
});
o.UseShardingTransaction((connection, builder) =>
{
builder.UseMySql(connection, new MySqlServerVersion(new Version())).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(efLogger);
});
o.AddDefaultDataSource("ds0","server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;");
})
.Build(sp);
stopwatch.Stop();
Console.WriteLine("ShardingRuntimeContext build:"+stopwatch.ElapsedMilliseconds);
return shardingRuntimeContext;
});
services.AddDbContext<DefaultShardingDbContext>(ShardingCoreExtension.UseDefaultSharding<DefaultShardingDbContext>);
// services.AddShardingDbContext<DefaultShardingDbContext>()
// .AddEntityConfig(o =>
// {
// o.CreateDataBaseOnlyOnStart = true;
// o.CreateShardingTableOnStart = true;
// o.EnsureCreatedWithOutShardingTable = true;
// o.IgnoreCreateTableError = true;
// o.AddShardingTableRoute<SysUserLogByMonthRoute>();
// o.AddShardingTableRoute<SysUserModVirtualTableRoute>();
// o.AddShardingDataSourceRoute<SysUserModVirtualDataSourceRoute>();
// o.UseShardingQuery((conStr, builder) =>
// {
// builder.UseMySql(conStr, new MySqlServerVersion(new Version())
// ,b=>b.EnableRetryOnFailure()
// )
// .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(efLogger);
// //builder.UseMySql(conStr, new MySqlServerVersion(new Version()));
// });
// o.UseShardingTransaction((connection, builder) =>
// {
// builder.UseMySql(connection, new MySqlServerVersion(new Version())
// ,b=>b.EnableRetryOnFailure()
// )
// .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking).UseLoggerFactory(efLogger);
// });
// })
// .AddConfig(op =>
// {
// op.ConfigId = "c0";
// op.AddDefaultDataSource("ds0",
// "server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;");
//
// //op.AddDefaultDataSource("ds0", "server=127.0.0.1;port=3306;database=db2;userid=root;password=L6yBtV6qNENrwBy7;")
// op.ReplaceTableEnsureManager(sp=>new MySqlTableEnsureManager<DefaultShardingDbContext>());
// }).EnsureConfig();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Console.WriteLine("11111");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseShardingCore();
// using (var scope = app.ApplicationServices.CreateScope())
// {
// var dbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();
// var shardingRuntimeContext = dbContext.GetService<IShardingRuntimeContext>();
// Console.WriteLine("123");
// }
// using (var scope = app.ApplicationServices.CreateScope())
// {
// var dbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();
// var shardingRuntimeContext = dbContext.GetService<IShardingRuntimeContext>();
// Console.WriteLine("1231");
// }
app.ApplicationServices.UseAutoShardingCore();
app.UseRouting();
app.UseAuthorization();

View File

@ -5,21 +5,16 @@ using Sample.SqlServer.DbContexts;
using Sample.SqlServer.Domain.Entities;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Extensions;
using ShardingCore.Extensions.ShardingPageExtensions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using ShardingCore;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions.ShardingQueryableExtensions;
using ShardingCore.Sharding.Abstractions;
using Microsoft.EntityFrameworkCore.Query.Internal;
using ShardingCore.EFCores;
using ShardingCore.Core;
using ShardingCore.Core.RuntimeContexts;
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
namespace Sample.SqlServer.Controllers
@ -36,39 +31,23 @@ namespace Sample.SqlServer.Controllers
private readonly DefaultShardingDbContext _defaultTableDbContext;
private readonly IShardingRouteManager _shardingRouteManager;
private readonly IShardingReadWriteManager _readWriteManager;
private readonly IShardingRuntimeContext _shardingRuntimeContext;
public ValuesController(DefaultShardingDbContext defaultTableDbContext, IShardingRouteManager shardingRouteManager,IShardingReadWriteManager readWriteManager)
public ValuesController(DefaultShardingDbContext defaultTableDbContext, IShardingRouteManager shardingRouteManager,IShardingReadWriteManager readWriteManager,IShardingRuntimeContext shardingRuntimeContext)
{
_defaultTableDbContext = defaultTableDbContext;
_ = defaultTableDbContext.Model;
_shardingRouteManager = shardingRouteManager;
_readWriteManager = readWriteManager;
_shardingRuntimeContext = shardingRuntimeContext;
}
[HttpGet]
public async Task<IActionResult> Get2x()
{
_defaultTableDbContext.ChangeTracker.HasChanges();
//var queryable = _defaultTableDbContext.Set<SysUserMod>().Where(o=>true);
//var tableRouteRuleEngineFactory = ShardingContainer.GetService<ITableRouteRuleEngineFactory<DefaultShardingDbContext>>();
//var tableRouteResults = tableRouteRuleEngineFactory.Route(queryable);
var virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<DefaultShardingDbContext>>();
var virtualTable = virtualTableManager.GetVirtualTable<SysUserMod>();
var physicTable1s = virtualTable.RouteTo(new ShardingTableRouteConfig(shardingKeyValue: "123"));//获取值为123的所有分片
Expression<Func<SysUserMod, bool>> where = o => o.Id == "123";
var physicTable2s = virtualTable.RouteTo(new ShardingTableRouteConfig(predicate: where));//获取表达式o.Id == "123"的所有路由
var allPhysicTables = virtualTable.GetAllPhysicTables();
var virtualTableRoute = virtualTable.GetVirtualRoute();
var allTails = virtualTableRoute.GetAllTails();
Console.WriteLine("------------------Get2x------------------------");
using (var dbContext =
DbContextHelper.CreateDbContextByString(
"Data Source=localhost;Initial Catalog=ShardingCoreDBXA;Integrated Security=True;"))
"Data Source=localhost;Initial Catalog=ShardingCoreDBXA;Integrated Security=True;",_shardingRuntimeContext))
{
await dbContext.AddAsync(new SysUserMod()
{

View File

@ -19,13 +19,6 @@ namespace Sample.SqlServer
*/
public static class DIExtension
{
public static IApplicationBuilder UseShardingCore(this IApplicationBuilder app)
{
var shardingBootstrapper = app.ApplicationServices.GetRequiredService<IShardingBootstrapper>();
shardingBootstrapper.Start();
return app;
}
public static void DbSeed(this IApplicationBuilder app)
{
using (var scope = app.ApplicationServices.CreateScope())

View File

@ -1,15 +1,17 @@
using Microsoft.EntityFrameworkCore;
using Sample.SqlServer.DbContexts;
using ShardingCore;
using ShardingCore.Core;
using ShardingCore.Core.RuntimeContexts;
namespace Sample.SqlServer
{
public class DbContextHelper
{
public static DbContext CreateDbContextByString(string connectionString)
public static DbContext CreateDbContextByString(string connectionString,IShardingRuntimeContext shardingRuntimeContext)
{
var dbContextOptionsBuilder = new DbContextOptionsBuilder<DefaultShardingDbContext>();
dbContextOptionsBuilder.UseSqlServer(connectionString).UseSharding<DefaultShardingDbContext>();
dbContextOptionsBuilder.UseSqlServer(connectionString).UseSharding<DefaultShardingDbContext>(shardingRuntimeContext);
return new DefaultShardingDbContext(dbContextOptionsBuilder.Options);
}
}

View File

@ -1,6 +1,5 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@ -8,17 +7,10 @@ using Sample.SqlServer.DbContexts;
using Sample.SqlServer.Shardings;
using Sample.SqlServer.UnionAllMerge;
using ShardingCore;
using ShardingCore.TableExists;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection.Extensions;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.EFCores.OptionsExtensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
namespace Sample.SqlServer
{
@ -41,25 +33,21 @@ namespace Sample.SqlServer
//services.AddDbContext<DefaultTableDbContext>(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx3;Integrated Security=True"));
services.AddShardingDbContext<DefaultShardingDbContext>()
.AddEntityConfig(o =>
.UseRouteConfig(o =>
{
o.ThrowIfQueryRouteNotMatch = false;
o.CreateShardingTableOnStart = true;
o.EnsureCreatedWithOutShardingTable = true;
o.AddShardingTableRoute<SysUserModVirtualTableRoute>();
o.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
o.AddShardingTableRoute<TestYearShardingVirtualTableRoute>();
})
.AddConfig(op =>
.UseConfig((sp,op) =>
{
op.ConfigId = "c1";
op.MaxQueryConnectionsLimit = 5;
op.UseSqlServer(builder =>
{
var loggerFactory = ShardingContainer.GetService<ILoggerFactory>();
var loggerFactory = sp.GetService<ILoggerFactory>();
builder.UseLoggerFactory(loggerFactory).UseUnionAllMerge<DefaultShardingDbContext>();
});
op.ReplaceTableEnsureManager(sp => new SqlServerTableEnsureManager<DefaultShardingDbContext>());
op.AddDefaultDataSource("A",
"Data Source=localhost;Initial Catalog=ShardingCoreDBXA;Integrated Security=True;"
);
@ -81,7 +69,7 @@ namespace Sample.SqlServer
new ReadNode("X","Data Source=localhost;Initial Catalog=ShardingCoreDBXA123;Integrated Security=True;"),
}}
},ReadStrategyEnum.Loop);
}).EnsureConfig();
}).AddShardingCore();
//services.AddShardingDbContext<DefaultShardingDbContext1>(
// (conn, o) =>
// o.UseSqlServer(conn).UseLoggerFactory(efLogger)
@ -137,15 +125,10 @@ namespace Sample.SqlServer
}
var startNew = Stopwatch.StartNew();
startNew.Start();
app.UseShardingCore();
startNew.Stop();
Console.WriteLine($"UseShardingCore:" + startNew.ElapsedMilliseconds + "ms");
app.UseRouting();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
DynamicShardingHelper.DynamicAppendDataSource<DefaultShardingDbContext>("c1","B", "Data Source=localhost;Initial Catalog=ShardingCoreDBXAABB;Integrated Security=True;");
// DynamicShardingHelper.DynamicAppendDataSource<DefaultShardingDbContext>("c1","B", "Data Source=localhost;Initial Catalog=ShardingCoreDBXAABB;Integrated Security=True;");
app.DbSeed();
}
}

View File

@ -11,7 +11,7 @@ namespace Sample.SqlServer.UnionAllMerge
{
public static class ShardingCoreSqlServerExtension
{
public static void UseSqlServer<TShardingDbContext>(this ShardingConfigOptions<TShardingDbContext> option,Action<DbContextOptionsBuilder> builderConfigure=null) where TShardingDbContext : DbContext, IShardingDbContext
public static void UseSqlServer(this ShardingConfigOptions option,Action<DbContextOptionsBuilder> builderConfigure=null)
{
option.UseShardingQuery((conStr, builder) =>
{

View File

@ -1,28 +0,0 @@
using Microsoft.EntityFrameworkCore.Metadata;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Extensions.InternalExtensions;
/*
* @Author: xjm
* @Description:
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
namespace ShardingCore.Bootstrappers
{
/// <summary>
/// 分表、分库对象确定参数用来初始化<see cref="EntityMetadata"/>时所需的信息
/// </summary>
public class EntityMetadataEnsureParams
{
public EntityMetadataEnsureParams(IEntityType entityType)
{
EntityType = entityType;
VirtualTableName = entityType.GetEntityTypeTableName();
}
public IEntityType EntityType { get; }
public string VirtualTableName { get; }
}
}

View File

@ -1,19 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.Logging;
using ShardingCore.Core;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.EntityShardingMetadatas;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
@ -33,36 +28,30 @@ namespace ShardingCore.Bootstrappers
/// <summary>
/// 对象元数据初始化器
/// </summary>
/// <typeparam name="TShardingDbContext"></typeparam>
/// <typeparam name="TEntity"></typeparam>
public class EntityMetadataInitializer<TShardingDbContext,TEntity>: IEntityMetadataInitializer where TShardingDbContext:DbContext,IShardingDbContext where TEntity:class
public class EntityMetadataInitializer<TEntity>: IEntityMetadataInitializer where TEntity:class
{
private static readonly ILogger<EntityMetadataInitializer<TShardingDbContext, TEntity>> _logger=InternalLoggerFactory.CreateLogger<EntityMetadataInitializer<TShardingDbContext,TEntity>>();
private const string QueryFilter = "QueryFilter";
private readonly IEntityType _entityType;
private readonly string _virtualTableName;
private readonly Expression<Func<TEntity,bool>> _queryFilterExpression;
private readonly IShardingEntityConfigOptions<TShardingDbContext> _shardingEntityConfigOptions;
private readonly IVirtualDataSourceManager<TShardingDbContext> _virtualDataSourceManager;
private readonly IVirtualDataSourceRouteManager<TShardingDbContext> _virtualDataSourceRouteManager;
private readonly IVirtualTableManager<TShardingDbContext> _virtualTableManager;
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private static readonly ILogger<EntityMetadataInitializer<TEntity>> _logger=ShardingLoggerFactory.CreateLogger<EntityMetadataInitializer<TEntity>>();
private readonly Type _shardingEntityType;
private readonly IShardingProvider _shardingProvider;
private readonly IShardingRouteConfigOptions _shardingRouteConfigOptions;
private readonly IVirtualDataSourceRouteManager _virtualDataSourceRouteManager;
private readonly ITableRouteManager _tableRouteManager;
private readonly IEntityMetadataManager _entityMetadataManager;
public EntityMetadataInitializer(EntityMetadataEnsureParams entityMetadataEnsureParams,
IShardingEntityConfigOptions<TShardingDbContext> shardingEntityConfigOptions,
IVirtualDataSourceManager<TShardingDbContext> virtualDataSourceManager,
IVirtualDataSourceRouteManager<TShardingDbContext> virtualDataSourceRouteManager,
IVirtualTableManager<TShardingDbContext> virtualTableManager,
IEntityMetadataManager<TShardingDbContext> entityMetadataManager
public EntityMetadataInitializer(
IShardingProvider shardingProvider,
IShardingRouteConfigOptions shardingRouteConfigOptions,
IVirtualDataSourceRouteManager virtualDataSourceRouteManager,
ITableRouteManager tableRouteManager,
IEntityMetadataManager entityMetadataManager
)
{
_entityType = entityMetadataEnsureParams.EntityType;
_virtualTableName = entityMetadataEnsureParams.VirtualTableName;
_queryFilterExpression = entityMetadataEnsureParams.EntityType.GetAnnotations().FirstOrDefault(o=>o.Name== QueryFilter)?.Value as Expression<Func<TEntity, bool>>;
_shardingEntityConfigOptions = shardingEntityConfigOptions;
_virtualDataSourceManager = virtualDataSourceManager;
_shardingEntityType = typeof(TEntity);
_shardingProvider = shardingProvider;
_shardingRouteConfigOptions = shardingRouteConfigOptions;
_virtualDataSourceRouteManager = virtualDataSourceRouteManager;
_virtualTableManager = virtualTableManager;
_tableRouteManager = tableRouteManager;
_entityMetadataManager = entityMetadataManager;
}
/// <summary>
@ -74,20 +63,18 @@ namespace ShardingCore.Bootstrappers
/// <exception cref="ShardingCoreInvalidOperationException"></exception>
public void Initialize()
{
var shardingEntityType = _entityType.ClrType;
var entityMetadata = new EntityMetadata(shardingEntityType, _virtualTableName,typeof(TShardingDbContext),_entityType.FindPrimaryKey()?.Properties?.Select(o=>o.PropertyInfo)?.ToList()??new List<PropertyInfo>(),_queryFilterExpression);
var entityMetadata = new EntityMetadata(_shardingEntityType);
if (!_entityMetadataManager.AddEntityMetadata(entityMetadata))
throw new ShardingCoreInvalidOperationException($"repeat add entity metadata {shardingEntityType.FullName}");
throw new ShardingCoreInvalidOperationException($"repeat add entity metadata {_shardingEntityType.FullName}");
//设置标签
if (_shardingEntityConfigOptions.TryGetVirtualDataSourceRoute<TEntity>(out var virtualDataSourceRouteType))
if (_shardingRouteConfigOptions.TryGetVirtualDataSourceRoute<TEntity>(out var virtualDataSourceRouteType))
{
var creatEntityMetadataDataSourceBuilder = EntityMetadataDataSourceBuilder<TEntity>.CreateEntityMetadataDataSourceBuilder(entityMetadata);
//配置属性分库信息
EntityMetadataHelper.Configure(creatEntityMetadataDataSourceBuilder);
var dataSourceRoute = CreateVirtualDataSourceRoute(virtualDataSourceRouteType, entityMetadata);
var dataSourceRoute = CreateVirtualDataSourceRoute(virtualDataSourceRouteType);
if (dataSourceRoute is IEntityMetadataAutoBindInitializer entityMetadataAutoBindInitializer)
{
entityMetadataAutoBindInitializer.Initialize(entityMetadata);
entityMetadataAutoBindInitializer.Initialize(entityMetadata,_shardingProvider);
}
//配置分库信息
if(dataSourceRoute is IEntityMetadataDataSourceConfiguration<TEntity> entityMetadataDataSourceConfiguration)
@ -98,19 +85,15 @@ namespace ShardingCore.Bootstrappers
entityMetadata.CheckShardingDataSourceMetadata();
}
if (_shardingEntityConfigOptions.TryGetVirtualTableRoute<TEntity>(out var virtualTableRouteType))
if (_shardingRouteConfigOptions.TryGetVirtualTableRoute<TEntity>(out var virtualTableRouteType))
{
if (!typeof(TShardingDbContext).IsShardingTableDbContext())
throw new ShardingCoreInvalidOperationException(
$"{typeof(TShardingDbContext)} is not impl {nameof(IShardingTableDbContext)},not support sharding table");
var entityMetadataTableBuilder = EntityMetadataTableBuilder<TEntity>.CreateEntityMetadataTableBuilder(entityMetadata);
//配置属性分表信息
EntityMetadataHelper.Configure(entityMetadataTableBuilder);
var virtualTableRoute = CreateVirtualTableRoute(virtualTableRouteType, entityMetadata);
var virtualTableRoute = CreateVirtualTableRoute(virtualTableRouteType);
if (virtualTableRoute is IEntityMetadataAutoBindInitializer entityMetadataAutoBindInitializer)
{
entityMetadataAutoBindInitializer.Initialize(entityMetadata);
entityMetadataAutoBindInitializer.Initialize(entityMetadata,_shardingProvider);
}
//配置分表信息
if (virtualTableRoute is IEntityMetadataTableConfiguration<TEntity> createEntityMetadataTableConfiguration)
@ -118,61 +101,30 @@ namespace ShardingCore.Bootstrappers
createEntityMetadataTableConfiguration.Configure(entityMetadataTableBuilder);
}
//创建虚拟表
var virtualTable = CreateVirtualTable(virtualTableRoute,entityMetadata);
_virtualTableManager.AddVirtualTable(virtualTable);
_tableRouteManager.AddRoute(virtualTableRoute);
//检测校验分表分库对象元数据
entityMetadata.CheckShardingTableMetadata();
//添加任务
if (virtualTableRoute is IJob routeJob && routeJob.AutoCreateTableByTime())
if (virtualTableRoute is IJob routeJob&&routeJob.AppendJob())
{
var jobManager = ShardingContainer.GetService<IJobManager>();
var jobEntry = JobEntryFactory.Create(routeJob);
jobManager.AddJob(jobEntry);
_shardingProvider.GetRequiredService<IJobManager>().AddJob(jobEntry);
}
}
entityMetadata.CheckGenericMetadata();
}
private IVirtualDataSourceRoute<TEntity> CreateVirtualDataSourceRoute(Type virtualRouteType,EntityMetadata entityMetadata)
private IVirtualDataSourceRoute<TEntity> CreateVirtualDataSourceRoute(Type virtualRouteType)
{
var constructors
= virtualRouteType.GetTypeInfo().DeclaredConstructors
.Where(c => !c.IsStatic && c.IsPublic)
.ToArray();
if (constructors.Length != 1)
{
throw new ArgumentException(
$"virtual route :[{virtualRouteType}] found more declared constructor ");
}
var @params = constructors[0].GetParameters().Select(x => ShardingContainer.GetService(x.ParameterType))
.ToArray();
object o = Activator.CreateInstance(virtualRouteType, @params);
return (IVirtualDataSourceRoute<TEntity>)o;
var instance = _shardingProvider.CreateInstance(virtualRouteType);
return (IVirtualDataSourceRoute<TEntity>)instance;
}
private IVirtualTableRoute<TEntity> CreateVirtualTableRoute(Type virtualRouteType, EntityMetadata entityMetadata)
private IVirtualTableRoute<TEntity> CreateVirtualTableRoute(Type virtualRouteType)
{
var constructors
= virtualRouteType.GetTypeInfo().DeclaredConstructors
.Where(c => !c.IsStatic && c.IsPublic)
.ToArray();
if (constructors.Length !=1)
{
throw new ArgumentException(
$"virtual route :[{virtualRouteType}] found more declared constructor ");
}
var @params = constructors[0].GetParameters().Select(x => ShardingContainer.GetService(x.ParameterType))
.ToArray();
object o = Activator.CreateInstance(virtualRouteType, @params);
return (IVirtualTableRoute<TEntity>)o;
}
private IVirtualTable<TEntity> CreateVirtualTable(IVirtualTableRoute<TEntity> virtualTableRoute,EntityMetadata entityMetadata)
{
return new DefaultVirtualTable<TEntity>(virtualTableRoute, entityMetadata);
var instance = _shardingProvider.CreateInstance(virtualRouteType);
return (IVirtualTableRoute<TEntity>)instance;
}
}
}

View File

@ -7,13 +7,10 @@
namespace ShardingCore.Bootstrappers
{
/// <summary>
/// 主要的分表启动器
/// 主要的分表初始化器,不再需要手动调用,<code>IShardingRuntimeContext初始化的时候会调用</code>
/// </summary>
public interface IShardingBootstrapper
{
/// <summary>
/// 启动
/// </summary>
void Start();
void AutoShardingTable();
}
}

View File

@ -0,0 +1,12 @@
namespace ShardingCore.Bootstrappers
{
internal interface IShardingInitializer
{
/// <summary>
/// 初始化
/// </summary>
void Initialize();
}
}

View File

@ -1,13 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ShardingCore.Core;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Jobs;
using ShardingCore.Jobs.Abstaractions;
using ShardingCore.Logger;
using ShardingCore.Sharding.MergeEngines.ParallelControl;
using ShardingCore.Sharding.ParallelTables;
namespace ShardingCore.Bootstrappers
{
@ -19,40 +27,49 @@ namespace ShardingCore.Bootstrappers
*/
public class ShardingBootstrapper : IShardingBootstrapper
{
private readonly ILogger<ShardingBootstrapper> _logger;
private readonly IEnumerable<IDbContextTypeCollector> _dbContextTypeCollectors;
private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce();
private readonly IShardingProvider _shardingProvider;
private readonly IDbContextCreator _dbContextCreator;
public ShardingBootstrapper(IServiceProvider serviceProvider,IEnumerable<IDbContextTypeCollector> dbContextTypeCollectors)
public ShardingBootstrapper(IShardingProvider shardingProvider,IDbContextCreator dbContextCreator)
{
ShardingContainer.SetServices(serviceProvider);
InternalLoggerFactory.DefaultFactory = serviceProvider.GetService<ILoggerFactory>();
_logger = InternalLoggerFactory.DefaultFactory .CreateLogger<ShardingBootstrapper>();
_dbContextTypeCollectors = dbContextTypeCollectors;
_shardingProvider = shardingProvider;
_dbContextCreator = dbContextCreator;
}
/// <summary>
/// 启动
/// </summary>
public void Start()
public void AutoShardingTable()
{
if (!_doOnlyOnce.IsUnDo())
return;
_logger.LogDebug("sharding core starting......");
foreach (var dbContextTypeCollector in _dbContextTypeCollectors)
{
var instance = (IShardingDbContextBootstrapper)ShardingContainer.CreateInstance(typeof(ShardingDbContextBootstrapper<>).GetGenericType0(dbContextTypeCollector.ShardingDbContextType));
_logger.LogDebug($"{dbContextTypeCollector.ShardingDbContextType} start init......");
instance.Init();
_logger.LogDebug($"{dbContextTypeCollector.ShardingDbContextType} complete init");
}
CheckRequirement();
StartAutoShardingJob();
}
var jobManager = ShardingContainer.GetService<IJobManager>();
if (jobManager != null && jobManager.HasAnyJob())
private void StartAutoShardingJob()
{
var jobRunnerService = _shardingProvider.GetRequiredService<JobRunnerService>(false);
Task.Factory.StartNew(async () =>
{
Task.Factory.StartNew(async () =>
await jobRunnerService.StartAsync();
}, TaskCreationOptions.LongRunning);
}
private void CheckRequirement()
{
try
{
using (var scope = _shardingProvider.CreateScope())
{
await ShardingContainer.GetService<JobRunnerService>().StartAsync();
}, TaskCreationOptions.LongRunning);
using (var dbContext = _dbContextCreator.GetShellDbContext(scope.ServiceProvider))
{
if (dbContext == null)
{
throw new ShardingCoreInvalidOperationException(
$"cant get shell db context,plz override {nameof(IDbContextCreator)}.{nameof(IDbContextCreator.GetShellDbContext)}");
}
}
}
}
catch (Exception ex)
{
throw new ShardingCoreInvalidOperationException(
$"cant get shell db context,plz override {nameof(IDbContextCreator)}.{nameof(IDbContextCreator.GetShellDbContext)}",
ex);
}
}

View File

@ -1,136 +0,0 @@
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.TrackerManagers;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.DynamicDataSources;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/20 14:04:55
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
namespace ShardingCore.Bootstrappers
{
/// <summary>
/// 分片具体DbContext初始化器
/// </summary>
public interface IShardingDbContextBootstrapper
{
/// <summary>
/// 初始化
/// </summary>
void Init();
}
/// <summary>
/// 分片具体DbContext初始化器
/// </summary>
public class ShardingDbContextBootstrapper<TShardingDbContext> : IShardingDbContextBootstrapper where TShardingDbContext : DbContext, IShardingDbContext
{
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(
IVirtualDataSourceManager<TShardingDbContext> virtualDataSourceManager,
IShardingEntityConfigOptions<TShardingDbContext> entityConfigOptions,
IEntityMetadataManager<TShardingDbContext> entityMetadataManager,
IParallelTableManager<TShardingDbContext> parallelTableManager,
IDataSourceInitializer<TShardingDbContext> dataSourceInitializer,
ITrackerManager<TShardingDbContext> trackerManager)
{
_shardingDbContextType = typeof(TShardingDbContext);
_virtualDataSourceManager = virtualDataSourceManager;
_entityConfigOptions = entityConfigOptions;
_entityMetadataManager = entityMetadataManager;
_parallelTableManager = parallelTableManager;
_dataSourceInitializer = dataSourceInitializer;
_trackerManager = trackerManager;
}
/// <summary>
/// 初始化
/// </summary>
public void Init()
{
InitializeEntityMetadata();
InitializeParallelTables();
InitializeConfigure();
}
private void InitializeEntityMetadata()
{
using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope())
{
var configId = _virtualDataSourceManager.GetAllVirtualDataSources().First().ConfigId;
using (_virtualDataSourceManager.CreateScope(configId))
{
//var dataSourceName = _virtualDataSource.DefaultDataSourceName;
using var context =
(DbContext)serviceScope.ServiceProvider.GetService(_shardingDbContextType);
foreach (var entity in context.Model.GetEntityTypes())
{
var entityType = entity.ClrType;
_trackerManager.AddDbContextModel(entityType,entity.FindPrimaryKey()!=null);
//entity.GetAnnotation("")
if (_entityConfigOptions.HasVirtualDataSourceRoute(entityType) ||
_entityConfigOptions.HasVirtualTableRoute(entityType))
{
var entityMetadataInitializerType = typeof(EntityMetadataInitializer<,>).GetGenericType1(_shardingDbContextType, entityType);
var entityMetadataInitializer = (IEntityMetadataInitializer)ShardingContainer.CreateInstanceWithInputParams(entityMetadataInitializerType, new EntityMetadataEnsureParams(entity));
entityMetadataInitializer.Initialize();
}
}
}
//if (_shardingConfigOption.EnsureCreatedWithOutShardingTable)
// EnsureCreated(context, dataSourceName);
}
}
private void InitializeParallelTables()
{
foreach (var parallelTableGroupNode in _entityConfigOptions.GetParallelTableGroupNodes())
{
var parallelTableComparerType = parallelTableGroupNode.GetEntities().FirstOrDefault(o => !_entityMetadataManager.IsShardingTable(o.Type));
if (parallelTableComparerType != null)
{
throw new ShardingCoreInvalidOperationException(
$"{parallelTableComparerType.Type.Name} must is sharding table type");
}
_parallelTableManager.AddParallelTable(parallelTableGroupNode);
}
}
private void InitializeConfigure()
{
var allVirtualDataSources = _virtualDataSourceManager.GetAllVirtualDataSources();
foreach (var virtualDataSource in allVirtualDataSources)
{
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

@ -0,0 +1,86 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Jobs;
using ShardingCore.Jobs.Abstaractions;
using ShardingCore.Logger;
using ShardingCore.Sharding.MergeEngines.ParallelControl;
using ShardingCore.Sharding.ParallelTables;
namespace ShardingCore.Bootstrappers
{
internal class ShardingInitializer:IShardingInitializer
{
private readonly ILogger<ShardingBootstrapper> _logger;
private readonly IShardingProvider _shardingProvider;
private readonly IShardingRouteConfigOptions _routeConfigOptions;
private readonly IEntityMetadataManager _entityMetadataManager;
private readonly IParallelTableManager _parallelTableManager;
private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce();
public ShardingInitializer(IShardingProvider shardingProvider)
{
_logger = ShardingLoggerFactory.DefaultFactory.CreateLogger<ShardingBootstrapper>();
_shardingProvider = shardingProvider;
_routeConfigOptions = shardingProvider.GetRequiredService<IShardingRouteConfigOptions>();
_entityMetadataManager = shardingProvider.GetRequiredService<IEntityMetadataManager>();
_parallelTableManager = shardingProvider.GetRequiredService<IParallelTableManager>();
}
/// <summary>
/// 初始化
/// </summary>
public void Initialize()
{
if (!_doOnlyOnce.IsUnDo())
return;
_logger.LogDebug("sharding core starting......");
_logger.LogDebug("sharding core initialize entity metadata......");
InitializeEntityMetadata();
_logger.LogDebug("sharding core initialize parallel table......");
InitializeParallelTables();
// _logger.LogDebug("sharding core check completeness......");
// CheckCompleteness();
_logger.LogDebug($"sharding core complete init");
_logger.LogDebug("sharding core running......");
}
private void InitializeEntityMetadata()
{
var shardingEntities = _routeConfigOptions.GetShardingTableRouteTypes()
.Concat(_routeConfigOptions.GetShardingDataSourceRouteTypes()).ToHashSet();
foreach (var entityType in shardingEntities)
{
var entityMetadataInitializerType =
typeof(EntityMetadataInitializer<>).GetGenericType0(entityType);
var entityMetadataInitializer =(IEntityMetadataInitializer)_shardingProvider.CreateInstance(entityMetadataInitializerType);
entityMetadataInitializer.Initialize();
}
}
private void InitializeParallelTables()
{
foreach (var parallelTableGroupNode in _routeConfigOptions.GetParallelTableGroupNodes())
{
var parallelTableComparerType = parallelTableGroupNode.GetEntities()
.FirstOrDefault(o => !_entityMetadataManager.IsShardingTable(o.Type));
if (parallelTableComparerType != null)
{
throw new ShardingCoreInvalidOperationException(
$"{parallelTableComparerType.Type.Name} must is sharding table type");
}
_parallelTableManager.AddParallelTable(parallelTableGroupNode);
}
}
}
}

View File

@ -14,7 +14,7 @@ namespace ShardingCore.Core
[ExcludeFromCodeCoverage]
private Check(){}
/// <summary>
/// 不能为空
/// 不能为空
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
@ -28,7 +28,7 @@ namespace ShardingCore.Core
return value;
}
/// <summary>
/// 应该为空
/// 应该为空
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>

View File

@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
namespace ShardingCore.Core.Collections
{
public class SafeReadAppendList<T>
{
private ImmutableList<T> _list;
public SafeReadAppendList(IEnumerable<T> list)
{
_list = ImmutableList.CreateRange(list);
}
public SafeReadAppendList():this(new List<T>(0))
{
}
public IReadOnlyList<T> Data => _list;
public void Append(T value)
{
ImmutableList<T> original;
ImmutableList<T> afterChange;
do
{
original = _list!;
afterChange = _list!.Add(value);
}
while (Interlocked.CompareExchange(ref _list, afterChange, original) != original);
}
}
}

View File

@ -4,8 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions;
@ -20,7 +19,7 @@ namespace ShardingCore.Core.DbContextCreator
/// Author: xjm
/// Created: 2022/4/2 21:15:09
/// Email: 326308290@qq.com
public class ActivatorDbContextCreator<TShardingDbContext>: IDbContextCreator<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class ActivatorDbContextCreator<TShardingDbContext>: IDbContextCreator where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly Func<ShardingDbContextOptions, DbContext> _creator;
public ActivatorDbContextCreator()
@ -34,7 +33,7 @@ namespace ShardingCore.Core.DbContextCreator
/// <param name="shellDbContext"></param>
/// <param name="shardingDbContextOptions"></param>
/// <returns></returns>
public DbContext CreateDbContext(DbContext shellDbContext, ShardingDbContextOptions shardingDbContextOptions)
public virtual DbContext CreateDbContext(DbContext shellDbContext, ShardingDbContextOptions shardingDbContextOptions)
{
var dbContext = _creator(shardingDbContextOptions);
if (dbContext is IShardingTableDbContext shardingTableDbContext)
@ -44,5 +43,10 @@ namespace ShardingCore.Core.DbContextCreator
_ = dbContext.Model;
return dbContext;
}
public virtual DbContext GetShellDbContext(IShardingProvider shardingProvider)
{
return shardingProvider.GetService<TShardingDbContext>();
}
}
}

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.DbContextCreator
@ -24,12 +25,13 @@ namespace ShardingCore.Core.DbContextCreator
/// <param name="shellDbContext">最外部的dbcontext也就是壳不具备真正的执行</param>
/// <param name="shardingDbContextOptions">返回dbcontext的配置路由等信息</param>
/// <returns></returns>
public DbContext CreateDbContext(DbContext shellDbContext, ShardingDbContextOptions shardingDbContextOptions);
}
public interface IDbContextCreator<TShardingDbContext> : IDbContextCreator
where TShardingDbContext : DbContext, IShardingDbContext
{
DbContext CreateDbContext(DbContext shellDbContext, ShardingDbContextOptions shardingDbContextOptions);
/// <summary>
/// 返回shell db context 框架如何获取db context
/// </summary>
/// <param name="shardingProvider"></param>
/// <returns></returns>
DbContext GetShellDbContext(IShardingProvider shardingProvider);
}
}

View File

@ -1,8 +1,11 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.EntityMetadatas
@ -10,8 +13,7 @@ namespace ShardingCore.Core.EntityMetadatas
/// <summary>
/// 默认分片对象元数据管理者实现
/// </summary>
/// <typeparam name="TShardingDbContext"></typeparam>
public class DefaultEntityMetadataManager<TShardingDbContext> : IEntityMetadataManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class DefaultEntityMetadataManager : IEntityMetadataManager
{
private readonly ConcurrentDictionary<Type, EntityMetadata> _caches =new ();
public bool AddEntityMetadata(EntityMetadata entityMetadata)
@ -72,5 +74,20 @@ namespace ShardingCore.Core.EntityMetadatas
{
return _caches.ContainsKey(entityType);
}
public List<Type> GetAllShardingEntities()
{
return _caches.Keys.ToList();
}
public bool TryInitModel(IEntityType efEntityType)
{
if (_caches.TryGetValue(efEntityType.ClrType,out var metadata))
{
metadata.SetEntityModel(efEntityType);
return true;
}
return false;
}
}
}

View File

@ -1,10 +1,14 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions;
namespace ShardingCore.Core.EntityMetadatas
{
@ -12,15 +16,10 @@ namespace ShardingCore.Core.EntityMetadatas
/// 分表或者分库对象的元数据信息记录对象在ShardingCore框架下的一些简单的信息
/// </summary>
public class EntityMetadata
{
public EntityMetadata(Type entityType, string virtualTableName,Type shardingDbContextType, IReadOnlyList<PropertyInfo> primaryKeyProperties,LambdaExpression queryFilterExpression)
{private const string QueryFilter = "QueryFilter";
public EntityMetadata(Type entityType)
{
EntityType = entityType;
VirtualTableName = virtualTableName;
ShardingDbContextType = shardingDbContextType;
PrimaryKeyProperties = primaryKeyProperties;
QueryFilterExpression = queryFilterExpression;
IsSingleKey= PrimaryKeyProperties.Count == 1;
ShardingDataSourceProperties = new Dictionary<string, PropertyInfo>();
ShardingTableProperties = new Dictionary<string, PropertyInfo>();
}
@ -28,26 +27,6 @@ namespace ShardingCore.Core.EntityMetadatas
/// 分表类型 sharding entity type
/// </summary>
public Type EntityType { get; }
/// <summary>
/// 分表的原表名 original table name in db exclude tail
/// </summary>
public string VirtualTableName { get; }
public Type ShardingDbContextType { get; }
/// <summary>
/// 主键
/// </summary>
public IReadOnlyList<PropertyInfo> PrimaryKeyProperties { get; }
/**
* efcore query filter
*/
public LambdaExpression QueryFilterExpression { get; }
/// <summary>
/// 是否单主键
/// </summary>
public bool IsSingleKey { get; }
/// <summary>
/// 是否多数据源
@ -91,6 +70,37 @@ namespace ShardingCore.Core.EntityMetadatas
/// 分表隔离器 table sharding tail prefix
/// </summary>
public string TableSeparator { get; private set; } = "_";
/// <summary>
/// 逻辑表名
/// </summary>
public string LogicTableName { get; private set; }
/// <summary>
/// 主键
/// </summary>
public IReadOnlyList<PropertyInfo> PrimaryKeyProperties { get; private set; }
/**
* efcore query filter
*/
public LambdaExpression QueryFilterExpression { get; private set; }
/// <summary>
/// 是否单主键
/// </summary>
public bool IsSingleKey { get; private set; }
public void SetEntityModel(IEntityType dbEntityType)
{
LogicTableName = dbEntityType.GetEntityTypeTableName();
QueryFilterExpression= dbEntityType.GetAnnotations().FirstOrDefault(o=>o.Name== QueryFilter)?.Value as LambdaExpression;
PrimaryKeyProperties = dbEntityType.FindPrimaryKey()?.Properties?.Select(o => o.PropertyInfo)?.ToList() ??
new List<PropertyInfo>();
IsSingleKey=PrimaryKeyProperties.Count == 1;
}
/// <summary>
/// 设置分库字段
/// </summary>
@ -179,7 +189,7 @@ namespace ShardingCore.Core.EntityMetadatas
/// </summary>
public void CheckGenericMetadata()
{
if (null == EntityType || null == PrimaryKeyProperties || null == VirtualTableName ||
if (null == EntityType ||
(!IsMultiTableMapping && !IsMultiDataSourceMapping))
{
throw new ShardingCoreException($"not found entity:{EntityType} configure");

View File

@ -1,14 +1,18 @@
namespace ShardingCore.Core.EntityMetadatas
using ShardingCore.Core.ServiceProviders;
namespace ShardingCore.Core.EntityMetadatas
{
/// <summary>
/// 元数据和路由绑定初始化器
/// </summary>
public interface IEntityMetadataAutoBindInitializer
{
IShardingProvider RouteShardingProvider { get; }
/// <summary>
/// 初始化 在启动时会被调用并且将对象元数据绑定到对应的路由上面
/// </summary>
/// <param name="entityMetadata"></param>
void Initialize(EntityMetadata entityMetadata);
/// <param name="shardingProvider"></param>
void Initialize(EntityMetadata entityMetadata,IShardingProvider shardingProvider);
}
}

View File

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.EntityMetadatas
@ -41,5 +43,9 @@ namespace ShardingCore.Core.EntityMetadatas
/// <param name="entityType"></param>
/// <returns></returns>
bool IsSharding(Type entityType);
List<Type> GetAllShardingEntities();
bool TryInitModel(IEntityType efEntityType);
}
}

View File

@ -1,14 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.EntityMetadatas
{
/// <summary>
/// 分片 对象元数据信息管理 可以通过依赖注入获取
/// </summary>
/// <typeparam name="TShardingDbContext"></typeparam>
public interface IEntityMetadataManager<TShardingDbContext>: IEntityMetadataManager where TShardingDbContext:DbContext,IShardingDbContext
{
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ShardingCore.Core
{
/*
* @Author: xjm
* @Description:
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
[Obsolete("will remove")]
public interface IShardingDataSource
{
}
}

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ShardingCore.Core
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/9/17 13:21:04
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
[Obsolete("will remove")]
public interface IShardingTable
{
}
}

View File

@ -1,96 +0,0 @@
using System;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.VirtualTables;
namespace ShardingCore.Core.PhysicTables
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 18 December 2020 13:57:50
* @Email: 326308290@qq.com
*/
/// <summary>
/// 默认的物理表
/// </summary>
public class DefaultPhysicTable : IPhysicTable
{
/// <summary>
/// 物理表
/// </summary>
/// <param name="virtualTable">虚拟表</param>
/// <param name="tail">物理表表后缀</param>
public DefaultPhysicTable(IVirtualTable virtualTable, string tail)
{
VirtualTable = virtualTable;
OriginalName = virtualTable.GetVirtualTableName();
Tail = tail;
EntityMetadata = VirtualTable.EntityMetadata;
EntityType = EntityMetadata.EntityType;
}
/// <summary>
/// 元数据对象
/// </summary>
public EntityMetadata EntityMetadata { get; }
/// <summary>
/// 全表名称
/// </summary>
public string FullName => $"{OriginalName}{TableSeparator}{Tail}";
/// <summary>
/// 原始表名
/// </summary>
public string OriginalName { get; }
/// <summary>
/// 分表的表名和后置的连接器默认为下划线"_" 可以为空
/// </summary>
public string TableSeparator => EntityMetadata.TableSeparator;
/// <summary>
/// 分表后缀
/// </summary>
public string Tail { get; }
/// <summary>
/// 类型对象
/// </summary>
public Type EntityType { get; }
/// <summary>
/// 所属虚拟表
/// </summary>
public IVirtualTable VirtualTable { get; }
protected bool Equals(DefaultPhysicTable other)
{
return OriginalName == other.OriginalName && Tail == other.Tail && Equals(EntityType, other.EntityType);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((DefaultPhysicTable)obj);
}
#if !EFCORE2
public override int GetHashCode()
{
return HashCode.Combine(OriginalName, Tail, VirtualTable);
}
#endif
#if EFCORE2
public override int GetHashCode()
{
unchecked
{
var hashCode = (OriginalName != null ? OriginalName.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Tail != null ? Tail.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (VirtualTable != null ? VirtualTable.GetHashCode() : 0);
return hashCode;
}
}
#endif
}
}

View File

@ -1,48 +0,0 @@
using System;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.VirtualTables;
/*
* @Author: xjm
* @Description:
* @Date: Friday, 18 December 2020 13:54:46
* @Email: 326308290@qq.com
*/
namespace ShardingCore.Core.PhysicTables
{
/// <summary>
/// 物理表接口
/// </summary>
public interface IPhysicTable
{
/// <summary>
/// 对象信息
/// </summary>
EntityMetadata EntityMetadata { get; }
/// <summary>
/// 表全称
/// </summary>
string FullName { get; }
/// <summary>
/// 原表名称
/// </summary>
string OriginalName { get; }
/// <summary>
/// 尾巴前缀 tail prefix
/// </summary>
string TableSeparator { get; }
/// <summary>
/// 尾巴
/// </summary>
string Tail { get; }
/// <summary>
/// 映射类类型
/// </summary>
Type EntityType { get; }
/// <summary>
/// 所属虚拟表
/// </summary>
IVirtualTable VirtualTable { get; }
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
namespace ShardingCore.Core.QueryRouteManagers.Abstractions
{
@ -15,7 +16,7 @@ namespace ShardingCore.Core.QueryRouteManagers.Abstractions
/// </summary>
public interface ITableRouteAssert
{
void Assert(List<IPhysicTable> allPhysicTables, List<IPhysicTable> resultPhysicTables);
void Assert(DataSourceRouteResult dataSourceRouteResult,List<string> tails, List<TableRouteUnit> shardingRouteUnits);
}
public interface ITableRouteAssert<T> : ITableRouteAssert where T : class

View File

@ -0,0 +1,50 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.QueryTrackers;
using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Core.TrackerManagers;
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.DynamicDataSources;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
namespace ShardingCore.Core.RuntimeContexts
{
public interface IShardingRuntimeContext
{
IShardingCompilerExecutor GetShardingCompilerExecutor();
IShardingReadWriteManager GetShardingReadWriteManager();
ITrackerManager GetTrackerManager();
IParallelTableManager GetParallelTableManager();
IDbContextCreator GetDbContextCreator();
IEntityMetadataManager GetEntityMetadataManager();
// IVirtualDataSourceManager GetVirtualDataSourceManager();
IVirtualDataSource GetVirtualDataSource();
ITableRouteManager GetTableRouteManager();
IRouteTailFactory GetRouteTailFactory();
IQueryTracker GetQueryTracker();
IUnionAllMergeManager GetUnionAllMergeManager();
IShardingPageManager GetShardingPageManager();
IDataSourceInitializer GetDataSourceInitializer();
void GetOrCreateShardingRuntimeModel(DbContext dbContext);
void UseLogfactory(ILoggerFactory loggerFactory);
void UseApplicationServiceProvider(IServiceProvider applicationServiceProvider);
void Initialize();
void AutoShardingTable();
object GetService(Type serviceType);
TService GetService<TService>();
object GetRequiredService(Type serviceType);
TService GetRequiredService<TService>();
}
}

View File

@ -0,0 +1,203 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ShardingCore.Bootstrappers;
using ShardingCore.Core.DbContextCreator;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Core.QueryTrackers;
using ShardingCore.Core.ShardingPage.Abstractions;
using ShardingCore.Core.TrackerManagers;
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.DynamicDataSources;
using ShardingCore.Exceptions;
using ShardingCore.Logger;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
namespace ShardingCore.Core.RuntimeContexts
{
public sealed class ShardingRuntimeContext:IShardingRuntimeContext
{
private bool isInited = false;
private object INIT_LOCK = new object();
private bool isInitModeled = false;
private object INIT_MODEL = new object();
private IServiceCollection _serviceMap = new ServiceCollection();
private IServiceProvider _serviceProvider;
private IServiceProvider _applicationServiceProvider;
public void AddServiceConfig(Action<IServiceCollection> configure)
{
CheckIfBuild();
configure(_serviceMap);
}
public void Initialize()
{
if (isInited)
return;
lock (INIT_LOCK)
{
if (isInited)
return;
isInited = true;
_serviceProvider = _serviceMap.BuildServiceProvider();
_serviceProvider.GetRequiredService<IShardingInitializer>().Initialize();
}
}
public void AutoShardingTable()
{
GetRequiredService<IShardingBootstrapper>().AutoShardingTable();
}
public IShardingCompilerExecutor GetShardingCompilerExecutor()
{
return GetRequiredService<IShardingCompilerExecutor>();
}
public IShardingReadWriteManager GetShardingReadWriteManager()
{
return GetRequiredService<IShardingReadWriteManager>();
}
public ITrackerManager GetTrackerManager()
{
return GetRequiredService<ITrackerManager>();
}
public IParallelTableManager GetParallelTableManager()
{
return GetRequiredService<IParallelTableManager>();
}
public IDbContextCreator GetDbContextCreator()
{
return GetRequiredService<IDbContextCreator>();
}
public IEntityMetadataManager GetEntityMetadataManager()
{
return GetRequiredService<IEntityMetadataManager>();
}
public IVirtualDataSource GetVirtualDataSource()
{
return GetRequiredService<IVirtualDataSource>();
}
public ITableRouteManager GetTableRouteManager()
{
return GetRequiredService<ITableRouteManager>();
}
public IRouteTailFactory GetRouteTailFactory()
{
return GetRequiredService<IRouteTailFactory>();
}
public IQueryTracker GetQueryTracker()
{
return GetRequiredService<IQueryTracker>();
}
public IUnionAllMergeManager GetUnionAllMergeManager()
{
return GetRequiredService<IUnionAllMergeManager>();
}
public IShardingPageManager GetShardingPageManager()
{
return GetRequiredService<IShardingPageManager>();
}
public IDataSourceInitializer GetDataSourceInitializer()
{
return GetRequiredService<IDataSourceInitializer>();
}
public void GetOrCreateShardingRuntimeModel(DbContext dbContext)
{
if (isInitModeled) return;
lock (INIT_MODEL)
{
if(isInitModeled) return;
isInitModeled = true;
var entityMetadataManager = GetService<IEntityMetadataManager>();
var entityTypes = dbContext.Model.GetEntityTypes();
foreach (var entityType in entityTypes)
{
entityMetadataManager.TryInitModel(entityType);
}
}
}
public void UseLogfactory(ILoggerFactory loggerFactory)
{
ShardingLoggerFactory.DefaultFactory = loggerFactory;
}
public void UseApplicationServiceProvider(IServiceProvider applicationServiceProvider)
{
_applicationServiceProvider = applicationServiceProvider;
}
private void CheckIfBuild()
{
if (isInited)
throw new InvalidOperationException("sharding runtime already build");
}
private void CheckIfNotBuild()
{
if (!isInited)
throw new InvalidOperationException("sharding runtime not init");
}
public object GetService(Type serviceType)
{
CheckIfNotBuild();
return _serviceProvider.GetService(serviceType);
}
public TService GetService<TService>()
{
CheckIfNotBuild();
return _serviceProvider.GetService<TService>();
}
public object GetRequiredService(Type serviceType)
{
CheckIfNotBuild();
return _serviceProvider.GetRequiredService(serviceType);
}
public TService GetRequiredService<TService>()
{
CheckIfNotBuild();
return _serviceProvider.GetRequiredService<TService>();
}
public IShardingRouteManager GetShardingRouteManager()
{
return GetRequiredService<IShardingRouteManager>();
}
//
// public IShardingRouteConfigOptions<TShardingDbContext> GetRequiredShardingEntityConfigOption<TShardingDbContext>()
// where TShardingDbContext : DbContext, IShardingDbContext
// {
// return (IShardingRouteConfigOptions<TShardingDbContext>)GetRequiredShardingEntityConfigOption(typeof(TShardingDbContext));
// }
// public IShardingRouteConfigOptions GetRequiredShardingEntityConfigOption(Type shardingDbContextType)
// {
// return (IShardingRouteConfigOptions)GetService(typeof(IShardingRouteConfigOptions<>).GetGenericType0(shardingDbContextType));
// }
}
}

View File

@ -0,0 +1,49 @@
using System;
namespace ShardingCore.Core.ServiceProviders
{
/// <summary>
/// 默认的分片服务提供者
/// </summary>
public interface IShardingProvider
{
/// <summary>
/// 优先通过ShardingCore的IServiceProvider获取
/// 没有再通过ApplicationServiceProvider获取
/// </summary>
/// <param name="serviceType"></param>
/// <param name="tryApplicationServiceProvider">是否尝试通过ApplicationServiceProvider获取</param>
/// <returns></returns>
object GetService(Type serviceType,bool tryApplicationServiceProvider=true);
/// <summary>
/// 优先通过ShardingCore的IServiceProvider获取
/// 没有再通过ApplicationServiceProvider获取
/// </summary>
/// <param name="tryApplicationServiceProvider">是否尝试通过ApplicationServiceProvider获取</param>
/// <typeparam name="TService"></typeparam>
/// <returns></returns>
TService GetService<TService>(bool tryApplicationServiceProvider=true);
/// <summary>
/// 优先通过ShardingCore的IServiceProvider获取
/// 没有再通过ApplicationServiceProvider获取
/// </summary>
/// <param name="serviceType"></param>
/// <param name="tryApplicationServiceProvider">是否尝试通过ApplicationServiceProvider获取</param>
/// <returns></returns>
object GetRequiredService(Type serviceType,bool tryApplicationServiceProvider=true);
/// <summary>
///
/// 优先通过ShardingCore的IServiceProvider获取
/// 没有再通过ApplicationServiceProvider获取
/// </summary>
/// <param name="tryApplicationServiceProvider">是否尝试通过ApplicationServiceProvider获取</param>
/// <typeparam name="TService"></typeparam>
/// <returns></returns>
TService GetRequiredService<TService>(bool tryApplicationServiceProvider=true);
IShardingScope CreateScope();
}
}

View File

@ -0,0 +1,9 @@
using System;
namespace ShardingCore.Core.ServiceProviders
{
public interface IShardingScope : IDisposable
{
IShardingProvider ServiceProvider { get; }
}
}

View File

@ -0,0 +1,52 @@
using System;
using Microsoft.Extensions.DependencyInjection;
namespace ShardingCore.Core.ServiceProviders
{
public class ShardingProvider:IShardingProvider
{
private readonly IServiceProvider _internalServiceProvider;
private readonly IServiceProvider _applicationServiceProvider;
public ShardingProvider(IServiceProvider internalServiceProvider,IServiceProvider applicationServiceProvider)
{
_internalServiceProvider = internalServiceProvider;
_applicationServiceProvider = applicationServiceProvider;
}
public object GetService(Type serviceType,bool tryApplicationServiceProvider=true)
{
var service = _internalServiceProvider?.GetService(serviceType);
if (tryApplicationServiceProvider&&service == null)
{
service= _applicationServiceProvider?.GetService(serviceType);
}
return service;
}
public TService GetService<TService>(bool tryApplicationServiceProvider=true)
{
return (TService)GetService(typeof(TService),tryApplicationServiceProvider);
}
public object GetRequiredService(Type serviceType,bool tryApplicationServiceProvider=true)
{
var service = GetService(serviceType,tryApplicationServiceProvider);
if (service == null)
{
throw new ArgumentNullException($"cant unable resolve service:[{serviceType}]");
}
return service;
}
public TService GetRequiredService<TService>(bool tryApplicationServiceProvider=true)
{
return (TService)GetRequiredService(typeof(TService),tryApplicationServiceProvider);
}
public IShardingScope CreateScope()
{
return new ShardingScope(_internalServiceProvider.CreateScope(), _applicationServiceProvider.CreateScope());
}
}
}

View File

@ -0,0 +1,27 @@
using Microsoft.Extensions.DependencyInjection;
namespace ShardingCore.Core.ServiceProviders
{
public class ShardingScope:IShardingScope
{
private readonly IServiceScope _internalServiceScope;
private readonly IServiceScope _applicationServiceScope;
private readonly IShardingProvider _shardingProvider;
public ShardingScope(IServiceScope internalServiceScope,IServiceScope applicationServiceScope)
{
_internalServiceScope = internalServiceScope;
_applicationServiceScope = applicationServiceScope;
_shardingProvider = new ShardingProvider(_internalServiceScope.ServiceProvider,
_applicationServiceScope.ServiceProvider);
}
public void Dispose()
{
_applicationServiceScope?.Dispose();
_internalServiceScope?.Dispose();
}
public IShardingProvider ServiceProvider =>_shardingProvider;
}
}

View File

@ -1,12 +0,0 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.ShardingConfigurations.Abstractions
{
public interface IShardingConfigurationOptions<TShardingDbContext> where TShardingDbContext:DbContext,IShardingDbContext
{
public void AddShardingGlobalConfigOptions(ShardingConfigOptions<TShardingDbContext> shardingConfigOptions);
public ShardingConfigOptions<TShardingDbContext>[] GetAllShardingGlobalConfigOptions();
}
}

View File

@ -1,26 +0,0 @@
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.Sharding.Abstractions;
namespace ShardingCore.Core.ShardingConfigurations.Abstractions
{
public interface IShardingEntityConfigOptions<TShardingDbContext> : IShardingEntityConfigOptions where TShardingDbContext : DbContext, IShardingDbContext
{
/// <summary>
/// 添加分库路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
void AddShardingDataSourceRoute<TRoute>() where TRoute : IVirtualDataSourceRoute;
/// <summary>
/// 添加分表路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
void AddShardingTableRoute<TRoute>() where TRoute : IVirtualTableRoute;
}
}

View File

@ -8,78 +8,99 @@ using System.Data.Common;
namespace ShardingCore.Core.ShardingConfigurations.Abstractions
{
public interface IShardingEntityConfigOptions
public interface IShardingRouteConfigOptions
{
/// <summary>
/// 如果数据库不存在就创建并且创建表除了分表的
/// </summary>
bool EnsureCreatedWithOutShardingTable { get; set; }
/// <summary>
/// 是否需要在启动时创建分表
/// </summary>
bool? CreateShardingTableOnStart { get; set; }
/// <summary>
/// 是否在启动时创建数据库
/// </summary>
public bool? CreateDataBaseOnlyOnStart { get; set; }
/// <summary>
/// 当查询遇到没有路由被命中时是否抛出错误
/// </summary>
bool ThrowIfQueryRouteNotMatch { get; set; }
// /// <summary>
// /// 如果数据库不存在就创建并且创建表除了分表的
// /// </summary>
// bool EnsureCreatedWithOutShardingTable { get; set; }
//
// /// <summary>
// /// 是否需要在启动时创建分表
// /// </summary>
// bool? CreateShardingTableOnStart { get; set; }
// /// <summary>
// /// 是否在启动时创建数据库
// /// </summary>
// public bool? CreateDataBaseOnlyOnStart { get; set; }
/// <summary>
/// 忽略建表时的错误
/// </summary>
bool? IgnoreCreateTableError { get; set; }
///// <summary>
///// 是否启用分表路由编译缓存(默认只缓存单个操作的也就是<![CDATA[=,>,>=,<,<=]]>)
///// default cache single filter route expression, <![CDATA[=,>,>=,<,<=]]> with sharding property
///// </summary>
//bool? EnableTableRouteCompileCache { get; set; }
///// <summary>
///// 是否启用分库路由编译缓存(默认只缓存单个操作的也就是<![CDATA[=,>,>=,<,<=]]>)
///// default cache single filter route expression, <![CDATA[=,>,>=,<,<=]]> with sharding property
///// </summary>
//bool? EnableDataSourceRouteCompileCache { get; set; }
// ///// <summary>
// ///// 是否启用分表路由编译缓存(默认只缓存单个操作的也就是<![CDATA[=,>,>=,<,<=]]>)
// ///// default cache single filter route expression, <![CDATA[=,>,>=,<,<=]]> with sharding property
// ///// </summary>
// //bool? EnableTableRouteCompileCache { get; set; }
// ///// <summary>
// ///// 是否启用分库路由编译缓存(默认只缓存单个操作的也就是<![CDATA[=,>,>=,<,<=]]>)
// ///// default cache single filter route expression, <![CDATA[=,>,>=,<,<=]]> with sharding property
// ///// </summary>
// //bool? EnableDataSourceRouteCompileCache { get; set; }
/// <summary>
/// 添加分库路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
void AddShardingDataSourceRoute<TRoute>() where TRoute : IVirtualDataSourceRoute;
/// <summary>
/// 添加分库路由
/// </summary>
/// <param name="routeType"></param>
void AddShardingDataSourceRoute(Type routeType);
/// <summary>
/// 添加分表路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
void AddShardingTableRoute<TRoute>() where TRoute : IVirtualTableRoute;
/// <summary>
/// 添加分表路由
/// </summary>
/// <param name="routeType"></param>
void AddShardingTableRoute(Type routeType);
/// <summary>
/// 是否有虚拟表路由
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
bool HasVirtualTableRoute(Type entityType);
/// <summary>
/// 获取虚拟表路由
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
Type GetVirtualTableRouteType(Type entityType);
/// <summary>
/// 是否有虚拟库路由
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
bool HasVirtualDataSourceRoute(Type entityType);
/// <summary>
/// 获取虚拟库路由
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
Type GetVirtualDataSourceRouteType(Type entityType);
/// <summary>
/// 获取所有的分表路由类型
/// </summary>
/// <returns></returns>
ISet<Type> GetShardingTableRouteTypes();
/// <summary>
/// 获取所有的分库路由类型
/// </summary>
@ -90,32 +111,26 @@ namespace ShardingCore.Core.ShardingConfigurations.Abstractions
/// 平行表
/// </summary>
bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode);
/// <summary>
/// 获取平行表
/// </summary>
/// <returns></returns>
ISet<ParallelTableGroupNode> GetParallelTableGroupNodes();
/// <summary>
/// DbContext如何通过现有connection创建
/// </summary>
Action<DbConnection, DbContextOptionsBuilder> ConnectionConfigure { get; }
/// <summary>
/// DbContext如何通过连接字符串创建
/// </summary>
Action<string, DbContextOptionsBuilder> ConnectionStringConfigure { get; }
Action<DbContextOptionsBuilder> ExecutorDbContextConfigure { get; }
Action<DbContextOptionsBuilder> ShellDbContextConfigure { get; }
// /// <summary>
// /// DbContext如何通过现有connection创建
// /// </summary>
// Action<DbConnection, DbContextOptionsBuilder> ConnectionConfigure { get; }
// /// <summary>
// /// DbContext如何通过连接字符串创建
// /// </summary>
// Action<string, DbContextOptionsBuilder> ConnectionStringConfigure { get; }
// Action<DbContextOptionsBuilder> ExecutorDbContextConfigure { get; }
// Action<DbContextOptionsBuilder> ShellDbContextConfigure { get; }
//
// void UseExecutorDbContextConfigure(Action<DbContextOptionsBuilder> executorDbContextConfigure);
// void UseShellDbContextConfigure(Action<DbContextOptionsBuilder> shellDbContextConfigure);
/// <summary>
/// DbContext如何通过连接字符串创建
/// </summary>
public void UseShardingQuery(Action<string, DbContextOptionsBuilder> queryConfigure);
/// <summary>
/// DbContext如何通过现有connection创建
/// </summary>
public void UseShardingTransaction(Action<DbConnection, DbContextOptionsBuilder> transactionConfigure);
void UseExecutorDbContextConfigure(Action<DbContextOptionsBuilder> executorDbContextConfigure);
void UseShellDbContextConfigure(Action<DbContextOptionsBuilder> shellDbContextConfigure);
}
}
}

View File

@ -1,165 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
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.ReadWriteConfigurations;
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
namespace ShardingCore.Core.ShardingConfigurations.ConfigBuilders
{
public class ShardingConfigBuilder<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
{
public ShardingCoreConfigBuilder<TShardingDbContext> ShardingCoreConfigBuilder { get; }
public ShardingConfigBuilder(ShardingCoreConfigBuilder<TShardingDbContext> shardingCoreConfigBuilder)
{
ShardingCoreConfigBuilder = shardingCoreConfigBuilder;
}
/// <summary>
/// 添加一个分片配置 必填<code>ConfigId</code>和<code>AddDefaultDataSource(string dataSourceName, string connectionString)</code>
/// 如果全局未配置 必须配置<code>UseShardingQuery</code>和<code>UseShardingQuery</code>
/// </summary>
/// <param name="shardingGlobalConfigOptionsConfigure"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ShardingCoreConfigException"></exception>
/// <exception cref="ArgumentException"></exception>
public ShardingConfigBuilder<TShardingDbContext> AddConfig(Action<ShardingConfigOptions<TShardingDbContext>> shardingGlobalConfigOptionsConfigure)
{
var shardingGlobalConfigOptions = new ShardingConfigOptions<TShardingDbContext>();
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(ShardingConfigOptions<TShardingDbContext>.AddDefaultDataSource)}");
if (string.IsNullOrWhiteSpace(shardingGlobalConfigOptions.DefaultConnectionString))
throw new ArgumentNullException(
$"{nameof(shardingGlobalConfigOptions.DefaultConnectionString)} plz call {nameof(ShardingConfigOptions<TShardingDbContext>.AddDefaultDataSource)}");
if (shardingGlobalConfigOptions.ConnectionStringConfigure is null&& ShardingCoreConfigBuilder.ShardingEntityConfigOptions.ConnectionStringConfigure is null)
throw new ArgumentNullException($"plz call {nameof(shardingGlobalConfigOptions.UseShardingQuery)}");
if (shardingGlobalConfigOptions.ConnectionConfigure is null && ShardingCoreConfigBuilder.ShardingEntityConfigOptions.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.ShardingConfigOptions.Add(shardingGlobalConfigOptions);
return this;
}
/// <summary>
/// 单配置确认
/// </summary>
/// <param name="configurationStrategy"></param>
/// <returns></returns>
public IServiceCollection EnsureConfig(ShardingConfigurationStrategyEnum configurationStrategy = ShardingConfigurationStrategyEnum.ThrowIfNull)
{
return DoEnsureConfig(false,false, configurationStrategy);
}
/// <summary>
/// 单配置确认 自动初始化不需要在手动<code>IShardingBootstrapper.Start()</code>
/// </summary>
/// <param name="configurationStrategy"></param>
/// <returns></returns>
public IServiceCollection EnsureConfigWithAutoStart(ShardingConfigurationStrategyEnum configurationStrategy = ShardingConfigurationStrategyEnum.ThrowIfNull)
{
return DoEnsureConfig(false,true, configurationStrategy);
}
/// <summary>
/// 多配置确认
/// </summary>
/// <param name="configurationStrategy"></param>
/// <returns></returns>
public IServiceCollection EnsureMultiConfig(ShardingConfigurationStrategyEnum configurationStrategy= ShardingConfigurationStrategyEnum.ThrowIfNull)
{
return DoEnsureConfig(true,false, configurationStrategy);
}
/// <summary>
/// 多配置确认 自动初始化不需要在手动<code>IShardingBootstrapper.Start()</code>
/// </summary>
/// <param name="configurationStrategy"></param>
/// <returns></returns>
public IServiceCollection EnsureMultiConfigWithAutoStart(ShardingConfigurationStrategyEnum configurationStrategy= ShardingConfigurationStrategyEnum.ThrowIfNull)
{
return DoEnsureConfig(true,true, configurationStrategy);
}
private IServiceCollection DoEnsureConfig(bool isMultiConfig,
bool autoStart,
ShardingConfigurationStrategyEnum configurationStrategy)
{
if (ShardingCoreConfigBuilder.ShardingConfigOptions.IsEmpty())
throw new ArgumentException($"plz call {nameof(AddConfig)} at least once ");
if (!isMultiConfig)
{
if (ShardingCoreConfigBuilder.ShardingConfigOptions.Count > 1)
{
throw new ArgumentException($"plz 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);
services.AddSingleton(sp => CreateShardingConfigurationOptions(isMultiConfig, configurationStrategy));
services.AddSingleton<IShardingReadWriteAccessor, ShardingReadWriteAccessor<TShardingDbContext>>();
if (autoStart)
{
}
services.AddInternalShardingCore<TShardingDbContext>();
return services;
}
private IShardingConfigurationOptions<TShardingDbContext> CreateShardingConfigurationOptions(bool isMultiConfig,
ShardingConfigurationStrategyEnum configurationStrategy)
{
IShardingConfigurationOptions<TShardingDbContext> shardingConfigurationOptions;
if (!isMultiConfig)
{
shardingConfigurationOptions = new ShardingSingleConfigurationOptions<TShardingDbContext>
{
ShardingConfigurationStrategy = configurationStrategy
};
}
else
{
shardingConfigurationOptions = new ShardingMultiConfigurationOptions<TShardingDbContext>
{
ShardingConfigurationStrategy = configurationStrategy
};
}
foreach (var configOptions in ShardingCoreConfigBuilder
.ShardingConfigOptions)
{
shardingConfigurationOptions.AddShardingGlobalConfigOptions(configOptions);
}
return shardingConfigurationOptions;
}
}
}

View File

@ -1,17 +1,12 @@
using System;
using System.Collections.Generic;
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.Core.RuntimeContexts;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ParallelTables;
namespace ShardingCore.DIExtensions
namespace ShardingCore.Core.ShardingConfigurations.ConfigBuilders
{
/*
* @Author: xjm
@ -20,114 +15,66 @@ namespace ShardingCore.DIExtensions
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ShardingCoreConfigBuilder<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
public class ShardingCoreConfigBuilder<TShardingDbContext> where TShardingDbContext:DbContext,IShardingDbContext
{
public IServiceCollection Services { get; }
private readonly IServiceCollection _services;
public List<ShardingConfigOptions<TShardingDbContext>> ShardingConfigOptions { get; }
public ShardingEntityConfigOptions<TShardingDbContext> ShardingEntityConfigOptions { get; }
private readonly ShardingRuntimeBuilder<TShardingDbContext> _shardingRuntimeBuilder;
public ShardingCoreConfigBuilder(IServiceCollection services)
{
Services = services;
ShardingConfigOptions = new List<ShardingConfigOptions<TShardingDbContext>>();
ShardingEntityConfigOptions = new ShardingEntityConfigOptions<TShardingDbContext>();
_services = services;
_shardingRuntimeBuilder = new ShardingRuntimeBuilder<TShardingDbContext>();
}
public ShardingConfigBuilder<TShardingDbContext> AddEntityConfig(Action<ShardingEntityConfigOptions<TShardingDbContext>> entityConfigure)
[Obsolete("plz use UseRouteConfig")]
public ShardingCoreConfigBuilder<TShardingDbContext> AddEntityConfig(Action<IShardingRouteConfigOptions> entityConfigure)
{
entityConfigure?.Invoke(ShardingEntityConfigOptions);
return new ShardingConfigBuilder<TShardingDbContext>(this);
_shardingRuntimeBuilder.UseRouteConfig(entityConfigure);
return this;
}
//public ShardingCoreConfigBuilder<TShardingDbContext, TActualDbContext> AddDefaultDataSource(string dataSourceName, string connectionString)
//{
// if (!string.IsNullOrWhiteSpace(defaultDataSourceName) || !string.IsNullOrWhiteSpace(defaultConnectionString))
// throw new ShardingCoreInvalidOperationException($"{nameof(AddDefaultDataSource)}-{dataSourceName}");
// this.defaultDataSourceName = dataSourceName;
// this.defaultConnectionString = connectionString;
// return this;
//}
//public ShardingCoreConfigBuilder<TShardingDbContext, TActualDbContext> AddDataSource(string dataSourceName, string connectionString)
//{
// if (_dataSources.ContainsKey(dataSourceName))
// throw new ShardingCoreInvalidOperationException($"{nameof(AddDataSource)}-{dataSourceName} repeat");
// _dataSources.Add(dataSourceName, connectionString);
// return this;
//}
}
public class ShardingCoreBeginOptions
{
/// <summary>
/// 配置id
/// </summary>
public string ConfigId { get; set; }
/// <summary>
/// 优先级
/// </summary>
public int Priority { get; set; }
/// <summary>
/// 如果数据库不存在就创建并且创建表除了分表的
/// </summary>
public bool EnsureCreatedWithOutShardingTable { get; set; }
/// <summary>
/// 是否需要在启动时创建分表
/// </summary>
public bool? CreateShardingTableOnStart { get; set; }
///// <summary>
///// 是否自动追踪实体
///// 譬如本次查询涉及到a1,a2,a3这三张表会创建3个dbcontext进行查询如果AutoTrackEntity=false那么针对被创建的dbcontext不会有任何变化还是以追踪的形式查询
///// 因为会同时创建3个dbcontext所以针对跨表查询完成后dbcontext会被回收但是查询还是按原先的行为查询所以如果不启用建议在查询的时候使用notracking
///// 如果AutoTrackEntity=true那么被创建的三个dbcontext还是以原先的表现行为进行查询在查询完成后会再次各自创建对应的dbcontext进行对象的追踪
///// </summary>
//public bool AutoTrackEntity { get; set; }
/// <summary>
/// 当查询遇到没有路由被命中时是否抛出错误
/// </summary>
public bool ThrowIfQueryRouteNotMatch { get; set; } = true;
/// <summary>
/// 忽略建表时的错误
/// </summary>
public bool? IgnoreCreateTableError { get; set; } = true;
public int MaxQueryConnectionsLimit { get; set; } = Environment.ProcessorCount;
public ConnectionModeEnum ConnectionMode { get; set; } = ConnectionModeEnum.SYSTEM_AUTO;
public bool? EnableTableRouteCompileCache { get; set; }
public bool? EnableDataSourceRouteCompileCache { get; set; }
private readonly ISet<Type> _createTableEntities = new HashSet<Type>();
public void AddEntitiesTryCreateTable(params Type[] entityTypes)
public ShardingCoreConfigBuilder<TShardingDbContext> UseRouteConfig(Action<IShardingRouteConfigOptions> routeConfigure)
{
foreach (var entityType in entityTypes)
{
_createTableEntities.Add(entityType);
}
_shardingRuntimeBuilder.UseRouteConfig(routeConfigure);
return this;
}
public ISet<Type> GetCreateTableEntities()
public ShardingCoreConfigBuilder<TShardingDbContext> UseRouteConfig(Action<IShardingProvider,IShardingRouteConfigOptions> routeConfigure)
{
return _createTableEntities;
_shardingRuntimeBuilder.UseRouteConfig(routeConfigure);
return this;
}
[Obsolete("plz use UseConfig")]
public ShardingCoreConfigBuilder<TShardingDbContext> AddConfig(Action<ShardingConfigOptions> shardingConfigure)
{
_shardingRuntimeBuilder.UseConfig(shardingConfigure);
return this;
}
public ShardingCoreConfigBuilder<TShardingDbContext> UseConfig(Action<ShardingConfigOptions> shardingConfigure)
{
_shardingRuntimeBuilder.UseConfig(shardingConfigure);
return this;
}
public ShardingCoreConfigBuilder<TShardingDbContext> UseConfig(Action<IShardingProvider,ShardingConfigOptions> shardingConfigure)
{
_shardingRuntimeBuilder.UseConfig(shardingConfigure);
return this;
}
public ShardingCoreConfigBuilder<TShardingDbContext> ReplaceService<TService, TImplement>(ServiceLifetime lifetime)
{
_shardingRuntimeBuilder.ReplaceService<TService, TImplement>(lifetime);
return this;
}
public readonly ISet<ParallelTableGroupNode> _parallelTables = new HashSet<ParallelTableGroupNode>();
public bool AddParallelTables(params Type[] types)
[Obsolete("plz use AddShardingCore")]
public void EnsureConfig()
{
if (types.Length <= 0)
throw new ShardingCoreInvalidOperationException(
$"{nameof(AddParallelTables)} args :[{string.Join(",", types.Select(o => o.Name))}] should more than one length");
return _parallelTables.Add(new ParallelTableGroupNode(types.Select(o => new ParallelTableComparerType(o))));
_services.AddSingleton<IShardingRuntimeContext>(sp => _shardingRuntimeBuilder.Build(sp));
}
public ISet<ParallelTableGroupNode> GetParallelTableGroupNodes()
public void AddShardingCore()
{
return _parallelTables;
_services.AddSingleton<IShardingRuntimeContext>(sp => _shardingRuntimeBuilder.Build(sp));
}
}
}

View File

@ -1,26 +1,14 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
using ShardingCore.TableExists;
using ShardingCore.TableExists.Abstractions;
using System;
using System.Collections.Generic;
using System.Data.Common;
using ShardingCore.Core.ServiceProviders;
namespace ShardingCore.Core.ShardingConfigurations
{
public class ShardingConfigOptions<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class ShardingConfigOptions
{
/// <summary>
/// 配置id,如果是单配置可以用guid代替,如果是多配置该属性表示每个配置的id
/// </summary>
public string ConfigId { get; set; }
/// <summary>
/// 优先级多个配置之间的优先级
/// </summary>
public int Priority { get; set; }
/// <summary>
/// 全局配置最大的查询连接数限制,默认系统逻辑处理器<code>Environment.ProcessorCount</code>
/// </summary>
@ -52,13 +40,13 @@ namespace ShardingCore.Core.ShardingConfigurations
DefaultDataSourceName= dataSourceName?? throw new ArgumentNullException(nameof(dataSourceName));
DefaultConnectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
}
public Func<IServiceProvider, IDictionary<string, string>> DataSourcesConfigure { get; private set; }
public Func<IShardingProvider, 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)
public void AddExtraDataSource(Func<IShardingProvider, IDictionary<string, string>> extraDataSourceConfigure)
{
DataSourcesConfigure= extraDataSourceConfigure ?? throw new ArgumentNullException(nameof(extraDataSourceConfigure));
}
@ -72,7 +60,7 @@ namespace ShardingCore.Core.ShardingConfigurations
/// <param name="readConnStringGetStrategy">LatestFirstTime:DbContext缓存,LatestEveryTime:每次都是最新</param>
/// <exception cref="ArgumentNullException"></exception>
public void AddReadWriteSeparation(
Func<IServiceProvider, IDictionary<string, IEnumerable<string>>> readWriteSeparationConfigure,
Func<IShardingProvider, IDictionary<string, IEnumerable<string>>> readWriteSeparationConfigure,
ReadStrategyEnum readStrategyEnum,
bool defaultEnable = false,
int defaultPriority = 10,
@ -86,7 +74,7 @@ namespace ShardingCore.Core.ShardingConfigurations
ShardingReadWriteSeparationOptions.ReadConnStringGetStrategy= readConnStringGetStrategy;
}
public void AddReadWriteNodeSeparation(
Func<IServiceProvider, IDictionary<string, IEnumerable<ReadNode>>> readWriteNodeSeparationConfigure,
Func<IShardingProvider, IDictionary<string, IEnumerable<ReadNode>>> readWriteNodeSeparationConfigure,
ReadStrategyEnum readStrategyEnum,
bool defaultEnable = false,
int defaultPriority = 10,
@ -153,27 +141,37 @@ namespace ShardingCore.Core.ShardingConfigurations
{
ShellDbContextConfigure = shellDbContextConfigure ?? throw new ArgumentNullException(nameof(shellDbContextConfigure));
}
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)
// public Func<IServiceProvider, ITableEnsureManager<TShardingDbContext>> TableEnsureManagerFactory =
// sp => new EmptyTableEnsureManager<TShardingDbContext>();
//
// public void ReplaceTableEnsureManager(
// Func<IServiceProvider, ITableEnsureManager<TShardingDbContext>> tableEnsureManagerConfigure)
// {
// TableEnsureManagerFactory = tableEnsureManagerConfigure ??
// throw new ArgumentNullException(nameof(tableEnsureManagerConfigure));
// }
public void CheckArguments()
{
ReplaceShardingComparerFactory = newShardingComparerFactory ?? throw new ArgumentNullException(nameof(newShardingComparerFactory));
if (string.IsNullOrWhiteSpace(DefaultDataSourceName))
throw new ArgumentNullException(
$"{nameof(DefaultDataSourceName)} plz call {nameof(AddDefaultDataSource)}");
if (string.IsNullOrWhiteSpace(DefaultConnectionString))
throw new ArgumentNullException(
$"{nameof(DefaultConnectionString)} plz call {nameof(AddDefaultDataSource)}");
if (ConnectionStringConfigure is null)
throw new ArgumentNullException($"plz call {nameof(UseShardingQuery)}");
if (ConnectionConfigure is null )
throw new ArgumentNullException(
$"plz call {nameof(UseShardingTransaction)}");
if (MaxQueryConnectionsLimit <= 0)
throw new ArgumentException(
$"{nameof(MaxQueryConnectionsLimit)} should greater than and equal 1");
}
public Func<IServiceProvider, ITableEnsureManager<TShardingDbContext>> TableEnsureManagerFactory =
sp => new EmptyTableEnsureManager<TShardingDbContext>();
public void ReplaceTableEnsureManager(
Func<IServiceProvider, ITableEnsureManager<TShardingDbContext>> tableEnsureManagerConfigure)
{
TableEnsureManagerFactory = tableEnsureManagerConfigure ??
throw new ArgumentNullException(nameof(tableEnsureManagerConfigure));
}
}
}

View File

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

View File

@ -1,13 +1,14 @@
using System;
using System.Collections.Generic;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Sharding.ReadWriteConfigurations;
namespace ShardingCore.Core.ShardingConfigurations
{
public class ShardingReadWriteSeparationOptions
{
public Func<IServiceProvider, IDictionary<string, IEnumerable<string>>> ReadWriteSeparationConfigure { get; set; }
public Func<IServiceProvider, IDictionary<string, IEnumerable<ReadNode>>> ReadWriteNodeSeparationConfigure { get; set; }
public Func<IShardingProvider, IDictionary<string, IEnumerable<string>>> ReadWriteSeparationConfigure { get; set; }
public Func<IShardingProvider, IDictionary<string, IEnumerable<ReadNode>>> ReadWriteNodeSeparationConfigure { get; set; }
public ReadStrategyEnum ReadStrategy { get; set; } = ReadStrategyEnum.Loop;
public bool DefaultEnable { get; set; } = false;

View File

@ -15,46 +15,49 @@ using ShardingCore.Sharding.ParallelTables;
namespace ShardingCore.Core.ShardingConfigurations
{
public class ShardingEntityConfigOptions<TShardingDbContext> : IShardingEntityConfigOptions<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class ShardingRouteConfigOptions : IShardingRouteConfigOptions
{
private readonly IDictionary<Type, Type> _virtualDataSourceRoutes = new Dictionary<Type, Type>();
private readonly IDictionary<Type, Type> _virtualTableRoutes = new Dictionary<Type, Type>();
private 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? CreateDataBaseOnlyOnStart { get; set; }
/// <summary>
/// 当查询遇到没有路由被命中时是否抛出错误
/// </summary>
public bool ThrowIfQueryRouteNotMatch { get; set; } = true;
///// <summary>
///// 全局启用分表路由表达式缓存,仅缓存单个表达式
///// </summary>
//public bool? EnableTableRouteCompileCache { get; set; }
///// <summary>
///// 全局启用分库路由表达式缓存,仅缓存单个表达式
///// </summary>
//public bool? EnableDataSourceRouteCompileCache { get; set; }
// /// <summary>
// /// 如果数据库不存在就创建并且创建表除了分表的
// /// </summary>
// public bool EnsureCreatedWithOutShardingTable { get; set; }
//
// /// <summary>
// /// 是否需要在启动时创建分表
// /// </summary>
// public bool? CreateShardingTableOnStart { get; set; }
// /// <summary>
// /// 是否在启动时创建数据库
// /// </summary>
// public bool? CreateDataBaseOnlyOnStart { get; set; }
// /// <summary>
// /// 当查询遇到没有路由被命中时是否抛出错误
// /// </summary>
// public bool ThrowIfQueryRouteNotMatch { get; set; } = true;
// ///// <summary>
// ///// 全局启用分表路由表达式缓存,仅缓存单个表达式
// ///// </summary>
// //public bool? EnableTableRouteCompileCache { get; set; }
// ///// <summary>
// ///// 全局启用分库路由表达式缓存,仅缓存单个表达式
// ///// </summary>
// //public bool? EnableDataSourceRouteCompileCache { get; set; }
/// <summary>
/// 忽略建表时的错误
/// </summary>
public bool? IgnoreCreateTableError { get; set; } = false;
public bool ThrowIfQueryRouteNotMatch { get; set; } = true;
/// <summary>
/// 添加分表路由
/// 添加分路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
public void AddShardingDataSourceRoute<TRoute>() where TRoute : IVirtualDataSourceRoute
public void AddShardingDataSourceRoute<TRoute>() where TRoute : IVirtualDataSourceRoute
{
var routeType = typeof(TRoute);
AddShardingDataSourceRoute(routeType);
@ -81,7 +84,7 @@ namespace ShardingCore.Core.ShardingConfigurations
/// 添加分表路由
/// </summary>
/// <typeparam name="TRoute"></typeparam>
public void AddShardingTableRoute<TRoute>() where TRoute : IVirtualTableRoute
public void AddShardingTableRoute<TRoute>() where TRoute : IVirtualTableRoute
{
var routeType = typeof(TRoute);
AddShardingTableRoute(routeType);
@ -151,48 +154,28 @@ namespace ShardingCore.Core.ShardingConfigurations
{
return _parallelTables;
}
/// <summary>
/// 多个DbContext事务传播委托
/// </summary>
public Action<DbConnection, DbContextOptionsBuilder> ConnectionConfigure { get; private set; }
/// <summary>
/// 初始DbContext的创建委托
/// </summary>
public Action<string, DbContextOptionsBuilder> ConnectionStringConfigure { get; private set; }
/// <summary>
/// 仅内部DbContext生效的配置委托
/// </summary>
public Action<DbContextOptionsBuilder> ExecutorDbContextConfigure { get; private set; }
public Action<DbContextOptionsBuilder> ShellDbContextConfigure { get; private set; }
/// <summary>
/// 如何使用字符串创建DbContext
/// </summary>
public void UseShardingQuery(Action<string, DbContextOptionsBuilder> queryConfigure)
{
ConnectionStringConfigure = queryConfigure ?? throw new ArgumentNullException(nameof(queryConfigure));
}
/// <summary>
/// 如何传递事务到其他DbContext
/// </summary>
public void UseShardingTransaction(Action<DbConnection, DbContextOptionsBuilder> transactionConfigure)
{
ConnectionConfigure = transactionConfigure ?? throw new ArgumentNullException(nameof(transactionConfigure));
}
/// <summary>
/// 仅内部真实DbContext配置的方法
/// </summary>
/// <param name="executorDbContextConfigure"></param>
/// <exception cref="ArgumentNullException"></exception>
public void UseExecutorDbContextConfigure(Action<DbContextOptionsBuilder> executorDbContextConfigure)
{
ExecutorDbContextConfigure = executorDbContextConfigure ?? throw new ArgumentNullException(nameof(executorDbContextConfigure));
}
public void UseShellDbContextConfigure(Action<DbContextOptionsBuilder> shellDbContextConfigure)
{
ShellDbContextConfigure = shellDbContextConfigure ?? throw new ArgumentNullException(nameof(shellDbContextConfigure));
}
// /// <summary>
// /// 仅内部DbContext生效的配置委托
// /// </summary>
// public Action<DbContextOptionsBuilder> ExecutorDbContextConfigure { get; private set; }
// public Action<DbContextOptionsBuilder> ShellDbContextConfigure { get; private set; }
//
// /// <summary>
// /// 仅内部真实DbContext配置的方法
// /// </summary>
// /// <param name="executorDbContextConfigure"></param>
// /// <exception cref="ArgumentNullException"></exception>
// public void UseExecutorDbContextConfigure(Action<DbContextOptionsBuilder> executorDbContextConfigure)
// {
// ExecutorDbContextConfigure = executorDbContextConfigure ?? throw new ArgumentNullException(nameof(executorDbContextConfigure));
// }
//
// public void UseShellDbContextConfigure(Action<DbContextOptionsBuilder> shellDbContextConfigure)
// {
// ShellDbContextConfigure = shellDbContextConfigure ?? throw new ArgumentNullException(nameof(shellDbContextConfigure));
// }
}
}

View File

@ -1,28 +0,0 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
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 ShardingConfigOptions<TShardingDbContext> _shardingConfigOptions;
public ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; set; } =
ShardingConfigurationStrategyEnum.ThrowIfNull;
public void AddShardingGlobalConfigOptions(ShardingConfigOptions<TShardingDbContext> shardingConfigOptions)
{
if (_shardingConfigOptions != null)
throw new ShardingCoreInvalidOperationException($"repeat add {nameof(ShardingConfigOptions<TShardingDbContext>)}");
_shardingConfigOptions= shardingConfigOptions;
}
public ShardingConfigOptions<TShardingDbContext>[] GetAllShardingGlobalConfigOptions()
{
return new[] { _shardingConfigOptions };
}
}
}

View File

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ShardingCore.Core
{
/*
* @Author: xjm
* @Description:
* @Date: 2021/8/21 13:04:38
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class ShardingConstant
{
public const string MULTI_ENTITIES_QUERY = "MULTI_ENTITIES_QUERY";
}
}

View File

@ -1,69 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ShardingCore.Core
{
internal class ShardingCreatorHelper
{
private static ConcurrentDictionary<Type, Func<object[], object>> _creator;
private ShardingCreatorHelper() { }
static ShardingCreatorHelper()
{
_creator = new ConcurrentDictionary<Type, Func<object[], object>>();
}
public static object CreateInstance(Type targetType,params object[] args)
{
var creator = _creator.GetOrAdd(targetType,key=> GetActivator(key));
return creator(args);
}
private static Func<object[],object> GetActivator(Type targetType)
{
ConstructorInfo ctor = targetType.GetConstructors().First();
Type type = ctor.DeclaringType;
ParameterInfo[] paramsInfo = ctor.GetParameters();
//create a single param of type object[]
ParameterExpression param =
Expression.Parameter(typeof(object[]), "args");
Expression[] argsExp =
new Expression[paramsInfo.Length];
//pick each arg from the params array
//and create a typed expression of them
for (int i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i].ParameterType;
Expression paramAccessorExp =
Expression.ArrayIndex(param, index);
Expression paramCastExp =
Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
//make a NewExpression that calls the
//ctor with the args we just created
NewExpression newExp = Expression.New(ctor, argsExp);
//create a lambda with the New
//Expression as body and our param object[] as arg
//compile it
var compiled =
Expression.Lambda<Func<object[],object>>(newExp, param).Compile();
return compiled;
}
}
}

View File

@ -1,22 +0,0 @@
using System;
namespace ShardingCore.Core
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 05 February 2021 12:53:46
* @Email: 326308290@qq.com
*/
/// <summary>
/// 数据源分库规则字段
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ShardingDataSourceKeyAttribute: Attribute
{
/// <summary>
/// 是否需要在启动的时候创建表
/// </summary>
public ShardingKeyAutoCreateTableEnum AutoCreateDataSourceTableOnStart { get; set; } = ShardingKeyAutoCreateTableEnum.UnKnown;
}
}

View File

@ -1,18 +0,0 @@
using System;
namespace ShardingCore.Core
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 05 February 2021 12:53:46
* @Email: 326308290@qq.com
*/
/// <summary>
/// 数据源分库额外规则字段
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ShardingExtraDataSourceKeyAttribute : Attribute
{
}
}

View File

@ -1,18 +0,0 @@
using System;
namespace ShardingCore.Core
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 16 December 2020 11:04:51
* @Email: 326308290@qq.com
*/
/// <summary>
/// 分片额外配置
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ShardingExtraTableKeyAttribute : Attribute
{
}
}

View File

@ -1,34 +0,0 @@
using System;
namespace ShardingCore.Core
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 16 December 2020 11:04:51
* @Email: 326308290@qq.com
*/
/// <summary>
/// AbstractVirtualTableRoute 最基础分表规则 需要自己解析如何分表
/// 仅ShardingMode为Custom:以下接口提供自定义分表
/// AbstractShardingKeyObjectEqualVirtualRoute 自定义分表
/// SimpleShardingKeyStringModVirtualRoute 默认对AbstractShardingKeyObjectEqualVirtualRoute的实现,字符串按取模分表
/// 仅ShardingMode非Custom以下接口提供自动按时间分表
/// SimpleShardingDateByDayVirtualRoute 分表
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ShardingTableKeyAttribute : Attribute
{
public const string DEFAULT_TABLE_SEPARATOR = "_";
/// <summary>
/// 是否需要在启动的时候创建表
/// </summary>
public ShardingKeyAutoCreateTableEnum AutoCreateTableOnStart { get; set; } = ShardingKeyAutoCreateTableEnum.UnKnown;
/// <summary>
/// 分表尾巴前缀
/// </summary>
public string TableSeparator { get; set; } = DEFAULT_TABLE_SEPARATOR;
}
}

View File

@ -19,7 +19,4 @@ namespace ShardingCore.Core.TrackerManagers
bool EntityUseTrack(Type entityType);
bool IsDbContextModel(Type entityType);
}
public interface ITrackerManager<TShardingDbContext>: ITrackerManager where TShardingDbContext:DbContext,IShardingDbContext
{
}
}

View File

@ -15,7 +15,7 @@ namespace ShardingCore.Core.TrackerManagers
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class TrackerManager<TShardingDbContext>: ITrackerManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class TrackerManager: ITrackerManager
{
private readonly ConcurrentDictionary<Type,bool> _dbContextModels = new ();

View File

@ -6,23 +6,14 @@ 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;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
using ShardingCore.TableExists;
using ShardingCore.TableExists.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
{
public abstract class AbstractVirtualDataSourceConfigurationParams<TShardingDbContext>:IVirtualDataSourceConfigurationParams<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
public abstract class AbstractVirtualDataSourceConfigurationParams:IVirtualDataSourceConfigurationParams
{
public abstract string ConfigId { get; }
public abstract int Priority { get; }
public virtual int MaxQueryConnectionsLimit { get; } = Environment.ProcessorCount;
public virtual ConnectionModeEnum ConnectionMode { get; } = ConnectionModeEnum.SYSTEM_AUTO;
public abstract string DefaultDataSourceName { get; }
@ -33,12 +24,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
public virtual bool? ReadWriteDefaultEnable { get; }
public virtual int? ReadWriteDefaultPriority { get; }
public virtual ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; }
public virtual IShardingComparer ShardingComparer { get; } = new CSharpLanguageShardingComparer();
public virtual ITableEnsureManager TableEnsureManager { get; } =
new EmptyTableEnsureManager<TShardingDbContext>();
public abstract DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
DbContextOptionsBuilder dbContextOptionsBuilder);

View File

@ -1,13 +0,0 @@
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

@ -4,20 +4,11 @@ using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
using System.Collections.Generic;
using System.Data.Common;
using ShardingCore.TableExists.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
{
public interface IVirtualDataSourceConfigurationParams
{
/// <summary>
/// 配置id
/// </summary>
string ConfigId { get; }
/// <summary>
/// 优先级
/// </summary>
int Priority { get; }
/// <summary>
/// 不能小于等于0 should greater than or equal zero
/// </summary>
@ -52,14 +43,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
/// </summary>
ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; }
/// <summary>
/// 不能为空 should not null
/// </summary>
IShardingComparer ShardingComparer { get; }
/// <summary>
/// 表确认管理者
/// </summary>
ITableEnsureManager TableEnsureManager { get; }
/// <summary>
/// 如何根据connectionString 配置 DbContextOptionsBuilder
/// </summary>
/// <param name="connectionString"></param>
@ -89,10 +72,4 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
/// <returns></returns>
bool UseReadWriteSeparation();
}
public interface IVirtualDataSourceConfigurationParams<TShardingDbContext> : IVirtualDataSourceConfigurationParams
where TShardingDbContext : DbContext, IShardingDbContext
{
}
}

View File

@ -1,40 +0,0 @@
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 GetCurrentVirtualDataSource();
IVirtualDataSource GetVirtualDataSource(string configId);
List<IVirtualDataSource> GetAllVirtualDataSources();
bool ContansConfigId(string configId);
/// <summary>
/// 创建分片配置scope
/// </summary>
/// <param name="configId"></param>
/// <returns></returns>
VirtualDataSourceScope CreateScope(string configId);
}
public interface IVirtualDataSourceManager<TShardingDbContext> : IVirtualDataSourceManager
where TShardingDbContext : DbContext, IShardingDbContext
{
IVirtualDataSource<TShardingDbContext> GetCurrentVirtualDataSource();
IVirtualDataSource<TShardingDbContext> GetVirtualDataSource(string configId);
List<IVirtualDataSource<TShardingDbContext>> GetAllVirtualDataSources();
bool AddVirtualDataSource(IVirtualDataSourceConfigurationParams<TShardingDbContext> configurationParams);
void SetDefaultIfMultiConfiguration();
}
}

View File

@ -27,11 +27,4 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
/// <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

@ -1,24 +0,0 @@
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

@ -2,12 +2,10 @@ 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;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.Abstractions;
@ -22,14 +20,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
public interface IVirtualDataSource
{
/// <summary>
/// 配置id
/// </summary>
string ConfigId { get; }
/// <summary>
/// 当前配置的优先级
/// </summary>
int Priority { get; }
/// <summary>
/// 数据源配置
/// </summary>
@ -129,12 +119,4 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
IDictionary<string, string> GetDataSources();
}
/// <summary>
/// 虚拟数据源 连接所有的实际数据源
/// </summary>
public interface IVirtualDataSource<TShardingDbContext> : IVirtualDataSource
where TShardingDbContext : DbContext, IShardingDbContext
{
IVirtualDataSourceRoute<TEntity> GetRoute<TEntity>() where TEntity:class;
}
}

View File

@ -1,29 +1,21 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.Sharding.ShardingComparision;
using ShardingCore.Sharding.ShardingComparision.Abstractions;
using ShardingCore.TableExists;
using ShardingCore.TableExists.Abstractions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.ServiceProviders;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
public class SimpleVirtualDataSourceConfigurationParams<TShardingDbContext>: AbstractVirtualDataSourceConfigurationParams<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
public class SimpleVirtualDataSourceConfigurationParams: AbstractVirtualDataSourceConfigurationParams
{
private readonly ShardingConfigOptions<TShardingDbContext> _options;
private readonly IShardingEntityConfigOptions<TShardingDbContext> _shardingEntityConfigOptions;
public override string ConfigId { get; }
public override int Priority { get; }
private readonly ShardingConfigOptions _options;
public override int MaxQueryConnectionsLimit { get; }
public override ConnectionModeEnum ConnectionMode { get; }
public override string DefaultDataSourceName { get; }
@ -34,29 +26,22 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
public override bool? ReadWriteDefaultEnable { get; }
public override int? ReadWriteDefaultPriority { get; }
public override ReadConnStringGetStrategyEnum? ReadConnStringGetStrategy { get; }
public override IShardingComparer ShardingComparer { get; }
public override ITableEnsureManager TableEnsureManager { get; }
public SimpleVirtualDataSourceConfigurationParams(IServiceProvider serviceProvider,ShardingConfigOptions<TShardingDbContext> options)
public SimpleVirtualDataSourceConfigurationParams(IShardingProvider shardingProvider,ShardingConfigOptions options)
{
_shardingEntityConfigOptions = serviceProvider.GetService<IShardingEntityConfigOptions<TShardingDbContext>>();
_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();
TableEnsureManager = options.TableEnsureManagerFactory?.Invoke(serviceProvider) ??
new EmptyTableEnsureManager<TShardingDbContext>();
ExtraDataSources = options.DataSourcesConfigure?.Invoke(shardingProvider)??new ConcurrentDictionary<string, string>();
if (options.ShardingReadWriteSeparationOptions != null)
{
if (options.ShardingReadWriteSeparationOptions.ReadWriteNodeSeparationConfigure != null)
{
var readConfig = options.ShardingReadWriteSeparationOptions.ReadWriteNodeSeparationConfigure?.Invoke(serviceProvider);
var readConfig = options.ShardingReadWriteSeparationOptions.ReadWriteNodeSeparationConfigure?.Invoke(shardingProvider);
if (readConfig != null)
{
ReadWriteNodeSeparationConfigs = readConfig.ToDictionary(kv=>kv.Key,kv=>kv.Value.ToArray());
@ -64,7 +49,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
}
else
{
var nodeConfig = options.ShardingReadWriteSeparationOptions.ReadWriteSeparationConfigure?.Invoke(serviceProvider);
var nodeConfig = options.ShardingReadWriteSeparationOptions.ReadWriteSeparationConfigure?.Invoke(shardingProvider);
if (nodeConfig != null)
{
ReadWriteNodeSeparationConfigs = nodeConfig.ToDictionary(kv => kv.Key,
@ -81,71 +66,43 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
DbContextOptionsBuilder dbContextOptionsBuilder)
{
if(_options.ConnectionStringConfigure==null&&_shardingEntityConfigOptions.ConnectionStringConfigure==null)
if(_options.ConnectionStringConfigure==null)
{
throw new InvalidOperationException($"unknown {nameof(UseDbContextOptionsBuilder)} by connection string");
}
if (_options.ConnectionStringConfigure != null)
{
_options.ConnectionStringConfigure.Invoke(connectionString, dbContextOptionsBuilder);
}
else
{
_shardingEntityConfigOptions.ConnectionStringConfigure.Invoke(connectionString, dbContextOptionsBuilder);
}
_options.ConnectionStringConfigure.Invoke(connectionString, dbContextOptionsBuilder);
return dbContextOptionsBuilder;
}
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection,
DbContextOptionsBuilder dbContextOptionsBuilder)
{
if (_options.ConnectionConfigure == null && _shardingEntityConfigOptions.ConnectionConfigure == null)
if (_options.ConnectionConfigure == null )
{
throw new InvalidOperationException($"unknown {nameof(UseDbContextOptionsBuilder)} by connection");
}
if (_options.ConnectionConfigure != null)
{
_options.ConnectionConfigure.Invoke(dbConnection, dbContextOptionsBuilder);
}
else
{
_shardingEntityConfigOptions.ConnectionConfigure.Invoke(dbConnection, dbContextOptionsBuilder);
}
_options.ConnectionConfigure.Invoke(dbConnection, dbContextOptionsBuilder);
return dbContextOptionsBuilder;
}
public override void UseShellDbContextOptionBuilder(DbContextOptionsBuilder dbContextOptionsBuilder)
{
if (_options.ShellDbContextConfigure == null && _shardingEntityConfigOptions.ShellDbContextConfigure == null)
if (_options.ShellDbContextConfigure == null)
{
return;
}
if (_options.ShellDbContextConfigure != null)
{
_options.ShellDbContextConfigure.Invoke(dbContextOptionsBuilder);
}
else
{
_shardingEntityConfigOptions.ShellDbContextConfigure?.Invoke(dbContextOptionsBuilder);
}
_options.ShellDbContextConfigure.Invoke(dbContextOptionsBuilder);
}
public override void UseExecutorDbContextOptionBuilder(DbContextOptionsBuilder dbContextOptionsBuilder)
{
if (_options.ExecutorDbContextConfigure == null && _shardingEntityConfigOptions.ExecutorDbContextConfigure == null)
if (_options.ExecutorDbContextConfigure == null )
{
return;
}
if (_options.ExecutorDbContextConfigure != null)
{
_options.ExecutorDbContextConfigure.Invoke(dbContextOptionsBuilder);
}
else
{
_shardingEntityConfigOptions.ExecutorDbContextConfigure?.Invoke(dbContextOptionsBuilder);
}
_options.ExecutorDbContextConfigure.Invoke(dbContextOptionsBuilder);
}
}
}

View File

@ -12,12 +12,12 @@ using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
using ShardingCore.Core.VirtualRoutes;
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.Sharding.ReadWriteConfigurations.Abstractions;
using ShardingCore.Utils;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
@ -28,27 +28,23 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
* @Date: Friday, 05 February 2021 15:21:04
* @Email: 326308290@qq.com
*/
public class VirtualDataSource<TShardingDbContext> : IVirtualDataSource<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class VirtualDataSource : IVirtualDataSource
{
public IVirtualDataSourceConfigurationParams ConfigurationParams { get; }
public IConnectionStringManager ConnectionStringManager { get; }
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private readonly IVirtualDataSourceRouteManager<TShardingDbContext> _dataSourceRouteManager;
private readonly IEntityMetadataManager _entityMetadataManager;
private readonly IVirtualDataSourceRouteManager _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, IVirtualDataSourceRouteManager<TShardingDbContext> dataSourceRouteManager, IVirtualDataSourceConfigurationParams<TShardingDbContext> configurationParams)
public VirtualDataSource(IEntityMetadataManager entityMetadataManager, IVirtualDataSourceRouteManager dataSourceRouteManager, IVirtualDataSourceConfigurationParams configurationParams,IReadWriteConnectorFactory readWriteConnectorFactory)
{
Check.NotNull(configurationParams, nameof(configurationParams));
Check.NotNull(configurationParams.ExtraDataSources, nameof(configurationParams.ExtraDataSources));
Check.NotNull(configurationParams.ShardingComparer, nameof(configurationParams.ShardingComparer));
if(configurationParams.MaxQueryConnectionsLimit<=0)
throw new ArgumentOutOfRangeException(nameof(configurationParams.MaxQueryConnectionsLimit));
ConfigurationParams = configurationParams;
@ -65,7 +61,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
if (UseReadWriteSeparation)
{
CheckReadWriteSeparation();
ConnectionStringManager = new ReadWriteConnectionStringManager(this);
ConnectionStringManager = new ReadWriteConnectionStringManager(this,readWriteConnectorFactory);
}
else
{
@ -99,11 +95,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
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))
@ -151,7 +142,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
/// <exception cref="ShardingCoreNotFoundException"></exception>
public IPhysicDataSource GetPhysicDataSource(string dataSourceName)
{
Check.NotNull(dataSourceName, "data source name is null,plz confirm IShardingBootstrapper.Star()");
Check.NotNull(dataSourceName, $"data source name is null,plz confirm {dataSourceName} add in virtual data source");
var dataSource = _physicDataSourcePool.TryGet(dataSourceName);
if (null == dataSource)
throw new ShardingCoreNotFoundException($"data source:[{dataSourceName}]");
@ -227,7 +218,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
DbContextOptionsBuilder dbContextOptionsBuilder)
{
var doUseDbContextOptionsBuilder = ConfigurationParams.UseDbContextOptionsBuilder(connectionString, dbContextOptionsBuilder);
doUseDbContextOptionsBuilder.UseInnerDbContextSharding<TShardingDbContext>();
doUseDbContextOptionsBuilder.UseInnerDbContextSharding();
ConfigurationParams.UseExecutorDbContextOptionBuilder(dbContextOptionsBuilder);
return doUseDbContextOptionsBuilder;
}
@ -236,7 +227,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
DbContextOptionsBuilder dbContextOptionsBuilder)
{
var doUseDbContextOptionsBuilder = ConfigurationParams.UseDbContextOptionsBuilder(dbConnection, dbContextOptionsBuilder);
doUseDbContextOptionsBuilder.UseInnerDbContextSharding<TShardingDbContext>();
doUseDbContextOptionsBuilder.UseInnerDbContextSharding();
ConfigurationParams.UseExecutorDbContextOptionBuilder(dbContextOptionsBuilder);
return doUseDbContextOptionsBuilder;
}

View File

@ -1,24 +0,0 @@
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

@ -1,18 +0,0 @@
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,170 +0,0 @@
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
{
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)
{
_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);
AddVirtualDataSource(simpleVirtualDataSourceConfigurationParams);
}
if (!IsMultiShardingConfiguration)
{
if (_defaultVirtualDataSource != null || _defaultConfigId != null)
throw new ShardingCoreInvalidOperationException("set sharding configuration error");
_defaultConfigId = _virtualDataSources.First().Key;
_defaultVirtualDataSource = _virtualDataSources.First().Value;
}
else if (ShardingConfigurationStrategy == ShardingConfigurationStrategyEnum.ReturnHighPriority)
{
var maxShardingConfiguration = _virtualDataSources.Values.OrderByDescending(o => o.Priority).FirstOrDefault();
_defaultVirtualDataSource = maxShardingConfiguration;
_defaultConfigId = maxShardingConfiguration.ConfigId;
}
}
public bool IsMultiShardingConfiguration { get; }
public ShardingConfigurationStrategyEnum ShardingConfigurationStrategy { get; }
public IVirtualDataSource GetCurrentVirtualDataSource()
{
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;
}
}
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}]");
}
}
IVirtualDataSource<TShardingDbContext> IVirtualDataSourceManager<TShardingDbContext>.GetVirtualDataSource(string configId)
{
return (IVirtualDataSource<TShardingDbContext>)GetVirtualDataSource(configId);
}
public IVirtualDataSource GetVirtualDataSource(string configId)
{
var hasValue = _virtualDataSources.TryGetValue(configId, out var virtualDataSource);
if (hasValue)
{
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}]");
}
}
List<IVirtualDataSource<TShardingDbContext>> IVirtualDataSourceManager<TShardingDbContext>.GetAllVirtualDataSources()
{
return GetAllVirtualDataSources().Select(o => (IVirtualDataSource<TShardingDbContext>)o).ToList();
}
public bool ContansConfigId(string configId)
{
return _virtualDataSources.ContainsKey(configId);
}
public bool AddVirtualDataSource(IVirtualDataSourceConfigurationParams<TShardingDbContext> configurationParams)
{
if (!IsMultiShardingConfiguration&&_virtualDataSources.IsNotEmpty())
throw new NotSupportedException("not support multi sharding configuration");
var dataSource = new VirtualDataSource<TShardingDbContext>(_entityMetadataManager, _virtualDataSourceRouteManager, configurationParams);
dataSource.CheckVirtualDataSource();
return _virtualDataSources.TryAdd(dataSource.ConfigId, dataSource);
}
public void SetDefaultIfMultiConfiguration()
{
if (IsMultiShardingConfiguration && ShardingConfigurationStrategy == ShardingConfigurationStrategyEnum.ReturnHighPriority)
{
var maxShardingConfiguration = _virtualDataSources.Values.OrderByDescending(o => o.Priority).FirstOrDefault();
if (maxShardingConfiguration.ConfigId != _defaultConfigId)
{
_defaultConfigId = maxShardingConfiguration.ConfigId;
_defaultVirtualDataSource = maxShardingConfiguration;
}
}
}
IVirtualDataSource<TShardingDbContext> IVirtualDataSourceManager<TShardingDbContext>.GetCurrentVirtualDataSource()
{
return (IVirtualDataSource<TShardingDbContext>)GetCurrentVirtualDataSource();
}
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

@ -16,17 +16,10 @@ using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
{
public class VirtualDataSourceRouteManager<TShardingDbContext> : IVirtualDataSourceRouteManager<TShardingDbContext>
where TShardingDbContext : DbContext, IShardingDbContext
public class VirtualDataSourceRouteManager : IVirtualDataSourceRouteManager
{
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));
@ -34,9 +27,9 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
public IVirtualDataSourceRoute GetRoute(Type entityType)
{
if (!_entityMetadataManager.IsShardingDataSource(entityType))
throw new ShardingCoreInvalidOperationException(
$"entity type :[{entityType.FullName}] not configure sharding data source");
// 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(

View File

@ -1,34 +0,0 @@
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

@ -1,130 +0,0 @@
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.PaginationConfigurations;
using ShardingCore.Utils;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.ShardingEnumerableQueries;
using ShardingCore.Core.VirtualDatabase;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Sharding.EntityQueryConfigurations;
namespace ShardingCore.Core.VirtualTables
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 18 December 2020 14:20:12
* @Email: 326308290@qq.com
*/
/// <summary>
/// 同数据库虚拟表
/// </summary>
/// <typeparam name="T"></typeparam>
public class DefaultVirtualTable<T> : IVirtualTable<T> where T : class
{
public EntityMetadata EntityMetadata { get; }
private readonly IVirtualTableRoute<T> _virtualTableRoute;
/// <summary>
/// 分页配置
/// </summary>
public PaginationMetadata PaginationMetadata { get; }
/// <summary>
/// 是否启用智能分页
/// </summary>
public bool EnablePagination => PaginationMetadata != null;
/// <summary>
/// 查询配置
/// </summary>
public EntityQueryMetadata EntityQueryMetadata { get; }
/// <summary>
/// 是否启用表达式分片配置
/// </summary>
public bool EnableEntityQuery => EntityQueryMetadata != null;
private readonly ConcurrentDictionary<IPhysicTable, object> _physicTables = new ConcurrentDictionary<IPhysicTable, object>();
public DefaultVirtualTable(IVirtualTableRoute<T> virtualTableRoute,EntityMetadata entityMetadata)
{
EntityMetadata = entityMetadata;
_virtualTableRoute = virtualTableRoute;
var paginationConfiguration = virtualTableRoute.CreatePaginationConfiguration();
if (paginationConfiguration!=null)
{
PaginationMetadata = new PaginationMetadata();
var paginationBuilder = new PaginationBuilder<T>(PaginationMetadata);
paginationConfiguration.Configure(paginationBuilder);
}
var entityQueryConfiguration = virtualTableRoute.CreateEntityQueryConfiguration();
if (entityQueryConfiguration != null)
{
EntityQueryMetadata = new EntityQueryMetadata();
var entityQueryBuilder = new EntityQueryBuilder<T>(EntityQueryMetadata);
entityQueryConfiguration.Configure(entityQueryBuilder);
}
}
public List<IPhysicTable> GetAllPhysicTables()
{
return _physicTables.Keys.ToList();
}
public List<IPhysicTable> RouteTo(ShardingTableRouteConfig tableRouteConfig)
{
var route = _virtualTableRoute;
if (tableRouteConfig.UseQueryable())
return route.RouteWithPredicate(GetAllPhysicTables(), tableRouteConfig.GetQueryable(), true);
if (tableRouteConfig.UsePredicate())
return route.RouteWithPredicate(GetAllPhysicTables(), new ShardingEmptyEnumerableQuery<T>((Expression<Func<T, bool>>)tableRouteConfig.GetPredicate()).EmptyQueryable(), false);
object shardingKeyValue = null;
if (tableRouteConfig.UseValue())
shardingKeyValue = tableRouteConfig.GetShardingKeyValue();
if (tableRouteConfig.UseEntity())
shardingKeyValue = tableRouteConfig.GetShardingEntity().GetPropertyValue(EntityMetadata.ShardingTableProperty.Name);
if (shardingKeyValue == null)
throw new ShardingCoreException(" route entity queryable or sharding key value is null ");
var routeWithValue = route.RouteWithValue(GetAllPhysicTables(), shardingKeyValue);
return new List<IPhysicTable>(1) { routeWithValue };
}
public bool AddPhysicTable(IPhysicTable physicTable)
{
if (physicTable.EntityType != EntityMetadata.EntityType)
throw new ShardingCoreInvalidOperationException($"virtual table entity type :[{EntityMetadata.EntityType.FullName}] physic table entity type:[{physicTable.EntityType.FullName}]");
return _physicTables.TryAdd(physicTable, null);
}
public string GetVirtualTableName()
{
return EntityMetadata.VirtualTableName;
}
IVirtualTableRoute IVirtualTable.GetVirtualRoute()
{
return GetVirtualRoute();
}
public List<string> GetTableAllTails()
{
return _physicTables.Keys.Select(o => o.Tail).ToList();
}
public IVirtualTableRoute<T> GetVirtualRoute()
{
return _virtualTableRoute;
}
}
}

View File

@ -1,84 +0,0 @@
using System;
using System.Collections.Generic;
using ShardingCore.Bootstrappers;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualDatabase;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Sharding.EntityQueryConfigurations;
using ShardingCore.Sharding.PaginationConfigurations;
namespace ShardingCore.Core.VirtualTables
{
/*
* @Author: xjm
* @Description:ef-core的表
* @Date: Friday, 18 December 2020 14:06:31
* @Email: 326308290@qq.com
*/
/// <summary>
/// 虚拟表
/// </summary>
public interface IVirtualTable
{
EntityMetadata EntityMetadata { get; }
/// <summary>
/// 分页配置
/// </summary>
PaginationMetadata PaginationMetadata { get; }
/// <summary>
/// 是否启用分页配置
/// </summary>
bool EnablePagination { get; }
/// <summary>
/// 查询配置
/// </summary>
EntityQueryMetadata EntityQueryMetadata { get; }
/// <summary>
/// 是否启用表达式分片配置
/// </summary>
bool EnableEntityQuery { get; }
/// <summary>
/// 获取所有的物理表
/// </summary>
/// <returns></returns>
List<IPhysicTable> GetAllPhysicTables();
/// <summary>
/// 路由到具体的物理表 which physic table route
/// </summary>
/// <param name="tableRouteConfig"></param>
/// <returns></returns>
List<IPhysicTable> RouteTo(ShardingTableRouteConfig tableRouteConfig);
/// <summary>
/// 添加物理表 add physic table
/// </summary>
/// <param name="physicTable"></param>
/// <returns>添加成功</returns>
bool AddPhysicTable(IPhysicTable physicTable);
/// <summary>
/// 获取原始表名 get original table name
/// </summary>
/// <returns></returns>
string GetVirtualTableName();
/// <summary>
/// 获取当前虚拟表的路由 get this virtual table route
/// </summary>
/// <returns></returns>
IVirtualTableRoute GetVirtualRoute();
/// <summary>
/// 获取启动时已经存在的表后缀 get this virtual table exists tails when app start
/// <see cref="ShardingBootstrapper"/> CreateDateTables
/// </summary>
/// <returns></returns>
List<string> GetTableAllTails();
}
public interface IVirtualTable<T> : IVirtualTable where T : class
{
new IVirtualTableRoute<T> GetVirtualRoute();
}
}

View File

@ -1,81 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualTables
{
/*
* @Author: xjm
* @Description: api
* @Date: Friday, 18 December 2020 14:10:03
* @Email: 326308290@qq.com
*/
public interface IVirtualTableManager
{
/// <summary>
/// 添加虚拟表应用启动时 add virtual table when app start
/// </summary>
/// <param name="virtualTable">虚拟表</param>
bool AddVirtualTable(IVirtualTable virtualTable);
/// <summary>
/// 获取虚拟表 get virtual table by sharding entity type
/// </summary>
/// <param name="shardingEntityType"></param>
/// <returns></returns>
IVirtualTable GetVirtualTable(Type shardingEntityType);
/// <summary>
/// 尝试获取虚拟表
/// </summary>
/// <param name="shardingEntityType"></param>
/// <returns></returns>
IVirtualTable TryGetVirtualTable(Type shardingEntityType);
/// <summary>
/// 获取虚拟表 get virtual table by actual table name
/// </summary>
/// <param name="virtualTableName"></param>
/// <returns></returns>
IVirtualTable GetVirtualTable(string virtualTableName);
/// <summary>
/// 尝试获取虚拟表没有返回null
/// </summary>
/// <param name="virtualTableName"></param>
/// <returns></returns>
IVirtualTable TryGetVirtualTable(string virtualTableName);
/// <summary>
/// 获取所有的虚拟表 get all virtual table
/// </summary>
/// <returns></returns>
ISet<IVirtualTable> GetAllVirtualTables();
/// <summary>
/// 添加物理表 add physic table
/// </summary>
/// <param name="virtualTable"></param>
/// <param name="physicTable"></param>
bool AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable);
/// <summary>
/// 添加物理表 add physic table
/// </summary>
/// <param name="shardingEntityType"></param>
/// <param name="physicTable"></param>
bool AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable);
}
/// <summary>
/// 虚拟表管理者 virtual table manager
/// </summary>
public interface IVirtualTableManager<TShardingDbContext> : IVirtualTableManager where TShardingDbContext : DbContext, IShardingDbContext
{
}
}

View File

@ -1,243 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.VirtualDatabase.VirtualTables
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 18 December 2020 14:52:42
* @Email: 326308290@qq.com
*/
/// <summary>
/// 同一个数据库下的虚拟表管理者
/// </summary>
public class VirtualTableManager<TShardingDbContext> : IVirtualTableManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
{
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
/// <summary>
/// {entityType,virtualTableType}
/// </summary>
private readonly ConcurrentDictionary<Type, IVirtualTable> _shardingVirtualTables = new ConcurrentDictionary<Type, IVirtualTable>();
private readonly ConcurrentDictionary<string, IVirtualTable> _shardingVirtualTaleVirtualTables = new ConcurrentDictionary<string, IVirtualTable>();
public VirtualTableManager(IEntityMetadataManager<TShardingDbContext> entityMetadataManager)
{
_entityMetadataManager = entityMetadataManager;
}
public bool AddVirtualTable(IVirtualTable virtualTable)
{
var result = _shardingVirtualTables.TryAdd(virtualTable.EntityMetadata.EntityType, virtualTable);
_shardingVirtualTaleVirtualTables.TryAdd(virtualTable.GetVirtualTableName(), virtualTable);
return result;
}
/// <summary>
/// 获取对应的虚拟表
/// </summary>
/// <param name="shardingEntityType"></param>
/// <returns></returns>
public IVirtualTable GetVirtualTable(Type shardingEntityType)
{
if (!_entityMetadataManager.IsShardingTable(shardingEntityType))
throw new ShardingCoreInvalidOperationException(shardingEntityType.FullName);
if (!_shardingVirtualTables.TryGetValue(shardingEntityType, out var virtualTable))
throw new ShardingCoreException($"virtual table not found entity: {shardingEntityType.FullName}");
return virtualTable;
}
public IVirtualTable TryGetVirtualTable(Type shardingEntityType)
{
if (!_entityMetadataManager.IsShardingTable(shardingEntityType))
throw new ShardingCoreInvalidOperationException(shardingEntityType.FullName);
if (!_shardingVirtualTables.TryGetValue(shardingEntityType, out var virtualTable))
return null;
return virtualTable;
}
public IVirtualTable GetVirtualTable(string virtualTableName)
{
if (!_shardingVirtualTaleVirtualTables.TryGetValue(virtualTableName, out var virtualTable))
throw new ShardingCoreException($"virtual table not found virtual table name: {virtualTableName}");
return virtualTable;
}
public IVirtualTable TryGetVirtualTable(string virtualTableName)
{
if (!_shardingVirtualTaleVirtualTables.TryGetValue(virtualTableName, out var virtualTable))
return null;
return virtualTable;
}
public ISet<IVirtualTable> GetAllVirtualTables()
{
return _shardingVirtualTables.Select(o => o.Value).ToHashSet();
}
public bool AddPhysicTable(IVirtualTable virtualTable, IPhysicTable physicTable)
{
return AddPhysicTable(virtualTable.EntityMetadata.EntityType, physicTable);
}
public bool AddPhysicTable(Type shardingEntityType, IPhysicTable physicTable)
{
if (!_shardingVirtualTables.TryGetValue(shardingEntityType, out var virtualTable))
throw new ShardingCoreException($"virtual table not found entity: {shardingEntityType.FullName}");
return virtualTable.AddPhysicTable(physicTable);
}
///// <summary>
///// {sharidngDbContextType:{entityType,virtualTableType}}
///// </summary>
//private readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, IVirtualTable>> _shardingVirtualTables = new ConcurrentDictionary<Type, ConcurrentDictionary<Type, IVirtualTable>>();
//private readonly ConcurrentDictionary<Type, ConcurrentDictionary<string, IVirtualTable>> _shardingVirtualTaleVirtualTables = new ConcurrentDictionary<Type, ConcurrentDictionary<string, IVirtualTable>>();
//public VirtualTableManager()
//{
//}
//private void CheckShardingDbContextType(Type shardingDbContextType)
//{
// if (!shardingDbContextType.IsShardingDbContext())
// throw new ShardingCoreException(
// $"{shardingDbContextType.FullName} must impl {nameof(IShardingDbContext)}");
//}
//private void CheckShardingTableEntityType(Type shardingEntityType)
//{
// if (!shardingEntityType.IsShardingTable())
// throw new ShardingCoreException(
// $"{shardingEntityType.FullName} must impl {nameof(IShardingTable)}");
//}
//private string CreateShardingEntityTypeKey(Type shardingDbContextType,Type entityType)
//{
// return $"{shardingDbContextType.FullName}{entityType.FullName}";
//}
//private string CreateShardingTableNameKey(Type shardingDbContextType,string originalTableName)
//{
// return $"{shardingDbContextType.FullName}{originalTableName}";
//}
//public void AddVirtualTable(Type shardingDbContextType,IVirtualTable virtualTable)
//{
// CheckShardingDbContextType(shardingDbContextType);
// var innerShardingVirtualTables = _shardingVirtualTables.GetOrAdd(shardingDbContextType,
// key => new ConcurrentDictionary<Type, IVirtualTable>());
// if (!innerShardingVirtualTables.ContainsKey(virtualTable.EntityType))
// {
// innerShardingVirtualTables.TryAdd(virtualTable.EntityType, virtualTable);
// }
// var innerShardingOriginalTableVirtualTables = _shardingVirtualTaleVirtualTables.GetOrAdd(shardingDbContextType,type=>new ConcurrentDictionary<string, IVirtualTable>());
// if (!innerShardingOriginalTableVirtualTables.ContainsKey(virtualTable.GetVirtualTableName()))
// {
// innerShardingOriginalTableVirtualTables.TryAdd(virtualTable.GetVirtualTableName(), virtualTable);
// }
//}
//public IVirtualTable GetVirtualTable(Type shardingDbContextType,Type shardingEntityType)
//{
// CheckShardingDbContextType(shardingDbContextType);
// CheckShardingTableEntityType(shardingEntityType);
// var shardingKey = CreateShardingEntityTypeKey(shardingDbContextType, shardingEntityType);
// if(!_shardingVirtualTables.TryGetValue(shardingDbContextType,out var innerShardingVirtualTables) || innerShardingVirtualTables.IsEmpty())
// throw new ShardingVirtualTableNotFoundException(shardingDbContextType.FullName);
// if (!innerShardingVirtualTables.TryGetValue(shardingEntityType, out var virtualTable)||virtualTable==null)
// throw new ShardingVirtualTableNotFoundException(shardingEntityType.FullName);
// return virtualTable;
//}
//public IVirtualTable<T> GetVirtualTable<TDbContext, T>() where T : class, IShardingTable where TDbContext : DbContext, IShardingDbContext
//{
// return (IVirtualTable<T>)GetVirtualTable(typeof(TDbContext), typeof(T));
//}
//public IVirtualTable GetVirtualTable(Type shardingDbContextType, string originalTableName)
//{
// CheckShardingDbContextType(shardingDbContextType);
// if (!_shardingVirtualTaleVirtualTables.TryGetValue(shardingDbContextType, out var innerShardingOriginalTableVirtualTables) || innerShardingOriginalTableVirtualTables.IsEmpty())
// throw new ShardingVirtualTableNotFoundException(shardingDbContextType.FullName);
// if(!innerShardingOriginalTableVirtualTables.TryGetValue(originalTableName,out var virtualTable)|| virtualTable==null)
// throw new ShardingVirtualTableNotFoundException(originalTableName);
// return virtualTable;
//}
//public IVirtualTable GetVirtualTable<TDbContext>(string originalTableName) where TDbContext : DbContext, IShardingDbContext
//{
// return GetVirtualTable(typeof(TDbContext),originalTableName);
//}
//public IVirtualTable TryGetVirtualTable(Type shardingDbContextType,string originalTableName)
//{
// CheckShardingDbContextType(shardingDbContextType);
// if (!_shardingVirtualTaleVirtualTables.TryGetValue(shardingDbContextType,
// out var innerShardingOriginalTableVirtualTables) || innerShardingOriginalTableVirtualTables.IsEmpty())
// return null;
// if (!innerShardingOriginalTableVirtualTables.TryGetValue(originalTableName, out var virtualTable) || virtualTable == null)
// return null;
// return virtualTable;
//}
//public IVirtualTable TryGetVirtualTablee<TDbContext>(string originalTableName) where TDbContext : DbContext, IShardingDbContext
//{
// return TryGetVirtualTable(typeof(TDbContext), originalTableName);
//}
//public List<IVirtualTable> GetAllVirtualTables(Type shardingDbContextType)
//{
// if (!_shardingVirtualTaleVirtualTables.TryGetValue(shardingDbContextType,
// out var innerShardingOriginalTableVirtualTables) || innerShardingOriginalTableVirtualTables.IsEmpty())
// return new List<IVirtualTable>();
// var keyPrefix = shardingDbContextType.FullName;
// return innerShardingOriginalTableVirtualTables.Values.ToList();
//}
//public List<IVirtualTable> GetAllVirtualTables<TDbContext>() where TDbContext : DbContext, IShardingDbContext
//{
// return GetAllVirtualTables(typeof(TDbContext));
//}
//public void AddPhysicTable(Type shardingDbContextType,IVirtualTable virtualTable, IPhysicTable physicTable)
//{
// AddPhysicTable(shardingDbContextType, virtualTable.EntityType, physicTable);
//}
//public void AddPhysicTable<TDbContext>(IVirtualTable virtualTable, IPhysicTable physicTable) where TDbContext : DbContext, IShardingDbContext
//{
// AddPhysicTable(typeof(TDbContext),virtualTable.EntityType, physicTable);
//}
//public void AddPhysicTable(Type shardingDbContextType,Type shardingEntityType, IPhysicTable physicTable)
//{
// var virtualTable = GetVirtualTable(shardingDbContextType,shardingEntityType);
// virtualTable.AddPhysicTable(physicTable);
//}
//public void AddPhysicTable<TDbContext>(Type shardingEntityType, IPhysicTable physicTable) where TDbContext : DbContext, IShardingDbContext
//{
// var virtualTable = GetVirtualTable(typeof(TDbContext),shardingEntityType);
// virtualTable.AddPhysicTable(physicTable);
//}
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Sharding.MergeEngines.Common.Abstractions;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
public interface ITableRouteManager
{
/// <summary>
/// 实体对象是否存在分表路由
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
bool HasRoute(Type entityType);
/// <summary>
/// 获取实体对象的分表路由,如果没有将抛出异常
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
/// <exception cref="ShardingCoreInvalidOperationException">如果没有找到对应的路由</exception>
IVirtualTableRoute GetRoute(Type entityType);
/// <summary>
/// 获取所有的分表路由
/// </summary>
/// <returns></returns>
List<IVirtualTableRoute> GetRoutes();
/// <summary>
/// 添加分表路由
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
/// <exception cref="ShardingCoreInvalidOperationException">如果当前路由的对象不是分表对象将抛出异常</exception>
bool AddRoute(IVirtualTableRoute route);
/// <summary>
/// 直接路由采用默认数据源
/// </summary>
/// <param name="entityType"></param>
/// <param name="shardingTableRouteConfig"></param>
/// <returns></returns>
List<TableRouteUnit> RouteTo(Type entityType,
ShardingTableRouteConfig shardingTableRouteConfig);
/// <summary>
/// 根据数据源路由进行分片路由
/// </summary>
/// <param name="entityType"></param>
/// <param name="dataSourceRouteResult"></param>
/// <param name="shardingTableRouteConfig"></param>
/// <returns></returns>
List<TableRouteUnit> RouteTo(Type entityType,DataSourceRouteResult dataSourceRouteResult,
ShardingTableRouteConfig shardingTableRouteConfig);
}
}

View File

@ -1,11 +0,0 @@
using System.Linq;
using ShardingCore.Sharding.MergeEngines.Common.Abstractions;
namespace ShardingCore.Core.VirtualRoutes.Abstracttions
{
// public interface IShardingRoute
// {
// ISqlRouteUnit RouteTo(IQueryable queryable);
// }
}

View File

@ -1,10 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
@ -25,8 +22,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
public abstract class AbstractShardingFilterVirtualDataSourceRoute<TEntity, TKey> : AbstractVirtualDataSourceRoute<TEntity, TKey> where TEntity : class
{
public ShardingRouteContext CurrentShardingRouteContext =>
ShardingContainer.GetService<IShardingRouteManager>().Current;
public ShardingRouteContext CurrentShardingRouteContext =>RouteShardingProvider.GetRequiredService<IShardingRouteManager>().Current;
/// <summary>
/// 启用提示路由
/// </summary>

View File

@ -2,9 +2,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Utils;

View File

@ -35,7 +35,7 @@
// {
// if (EnableRouteParseCompileCache.HasValue)
// return EnableRouteParseCompileCache.Value;
// return EntityConfigOptions.EnableDataSourceRouteCompileCache.GetValueOrDefault();
// return RouteConfigOptions.EnableDataSourceRouteCompileCache.GetValueOrDefault();
// }
// /// <summary>

View File

@ -5,6 +5,8 @@ using ShardingCore.Sharding.MergeEngines.ParallelControl;
using ShardingCore.Sharding.PaginationConfigurations;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Extensions;
using ShardingCore.Sharding.EntityQueryConfigurations;
namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
@ -19,7 +21,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
{
public EntityMetadata EntityMetadata { get; private set; }
private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce();
public IShardingEntityConfigOptions EntityConfigOptions { get; private set; }
// public IShardingRouteConfigOptions RouteConfigOptions { get; private set; }
public new PaginationMetadata PaginationMetadata { get; protected set; }
public bool EnablePagination => PaginationMetadata != null;
@ -27,11 +29,15 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
//public new EntityQueryMetadata EntityQueryMetadata { get; protected set; }
//public bool EnableEntityQuery => EnableEntityQuery != null;
public void Initialize(EntityMetadata entityMetadata)
public IShardingProvider RouteShardingProvider { get; private set;}
public void Initialize(EntityMetadata entityMetadata,IShardingProvider shardingProvider)
{
if (!_doOnlyOnce.IsUnDo())
throw new ShardingCoreInvalidOperationException("already init");
EntityMetadata = entityMetadata;
// RouteConfigOptions = shardingProvider.GetService<IShardingRouteConfigOptions>();
var paginationConfiguration = CreatePaginationConfiguration();
if (paginationConfiguration != null)
{
@ -39,18 +45,13 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions
var paginationBuilder = new PaginationBuilder<TEntity>(PaginationMetadata);
paginationConfiguration.Configure(paginationBuilder);
}
//var entityQueryConfiguration = CreateEntityQueryConfiguration();
//if (entityQueryConfiguration != null)
//{
// EntityQueryMetadata = new EntityQueryMetadata();
// var entityQueryBuilder= new EntityQueryBuilder<TEntity>(EntityQueryMetadata);
// entityQueryConfiguration.Configure(entityQueryBuilder);
//}
EntityConfigOptions =
ShardingContainer.GetRequiredShardingEntityConfigOption(entityMetadata.ShardingDbContextType);
// var entityQueryConfiguration = CreateEntityQueryConfiguration();
// if (entityQueryConfiguration != null)
// {
// EntityQueryMetadata = new EntityQueryMetadata();
// var entityQueryBuilder= new EntityQueryBuilder<TEntity>(EntityQueryMetadata);
// entityQueryConfiguration.Configure(entityQueryBuilder);
// }
}
public virtual IPaginationConfiguration<TEntity> CreatePaginationConfiguration()
{

View File

@ -18,6 +18,9 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
{
IntersectDataSources = intersectDataSources;
}
public DataSourceRouteResult(string dataSource):this(new HashSet<string>(){dataSource})
{
}
/// <summary>
/// 交集
/// </summary>

View File

@ -19,11 +19,11 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
* @Ver: 1.0
* @Email: 326308290@qq.com
*/
public class DataSourceRouteRuleEngine<TShardingDbContext> : IDataSourceRouteRuleEngine<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class DataSourceRouteRuleEngine: IDataSourceRouteRuleEngine
{
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
private readonly IEntityMetadataManager _entityMetadataManager;
public DataSourceRouteRuleEngine(IEntityMetadataManager<TShardingDbContext> entityMetadataManager)
public DataSourceRouteRuleEngine(IEntityMetadataManager entityMetadataManager)
{
_entityMetadataManager = entityMetadataManager;
}

View File

@ -18,14 +18,14 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
/// <summary>
/// 分库路由引擎工程
/// </summary>
public class DataSourceRouteRuleEngineFactory<TShardingDbContext>: IDataSourceRouteRuleEngineFactory<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
public class DataSourceRouteRuleEngineFactory: IDataSourceRouteRuleEngineFactory
{
private readonly IDataSourceRouteRuleEngine<TShardingDbContext> _dataSourceRouteRuleEngine;
private readonly IDataSourceRouteRuleEngine _dataSourceRouteRuleEngine;
/// <summary>
/// ctor
/// </summary>
/// <param name="dataSourceRouteRuleEngine"></param>
public DataSourceRouteRuleEngineFactory(IDataSourceRouteRuleEngine<TShardingDbContext> dataSourceRouteRuleEngine)
public DataSourceRouteRuleEngineFactory(IDataSourceRouteRuleEngine dataSourceRouteRuleEngine)
{
_dataSourceRouteRuleEngine = dataSourceRouteRuleEngine;
}

View File

@ -18,9 +18,4 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
DataSourceRouteResult Route(DataSourceRouteRuleContext routeRuleContext);
}
public interface IDataSourceRouteRuleEngine<TShardingDbContext> : IDataSourceRouteRuleEngine
where TShardingDbContext : DbContext, IShardingDbContext
{
}
}

View File

@ -20,8 +20,4 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext, Dictionary<Type, IQueryable> queryEntities);
//DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext);
}
public interface IDataSourceRouteRuleEngineFactory<TShardingDbContext> : IDataSourceRouteRuleEngineFactory
where TShardingDbContext : DbContext, IShardingDbContext
{
}
}

View File

@ -1,3 +1,5 @@
using System.Linq;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
@ -12,8 +14,15 @@ namespace ShardingCore.Core.VirtualRoutes
* @Date: Sunday, 22 August 2021 14:58:58
* @Email: 326308290@qq.com
*/
public class RouteTailFactory:IRouteTailFactory
public class RouteTailFactory : IRouteTailFactory
{
private readonly IEntityMetadataManager _entityMetadataManager;
public RouteTailFactory(IEntityMetadataManager entityMetadataManager)
{
_entityMetadataManager = entityMetadataManager;
}
public IRouteTail Create(string tail)
{
return Create(tail, true);
@ -33,7 +42,7 @@ namespace ShardingCore.Core.VirtualRoutes
public IRouteTail Create(TableRouteResult tableRouteResult)
{
return Create(tableRouteResult,true);
return Create(tableRouteResult, true);
}
public IRouteTail Create(TableRouteResult tableRouteResult, bool cache)
@ -61,7 +70,10 @@ namespace ShardingCore.Core.VirtualRoutes
return new NoCacheSingleQueryRouteTail(tableRouteResult);
}
}
return new MultiQueryRouteTail(tableRouteResult);
var isShardingTableQuery = tableRouteResult.ReplaceTables.Select(o => o.EntityType)
.Any(o => _entityMetadataManager.IsShardingTable(o));
return new MultiQueryRouteTail(tableRouteResult, isShardingTableQuery);
}
}
}

View File

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Sharding.MergeEngines.Common.Abstractions;
namespace ShardingCore.Core.VirtualRoutes
{
public class ShardingRouteResult
{
public IReadOnlyList<ISqlRouteUnit> RouteUnits { get; }
public bool IsCrossDataSource { get; }
public bool IsCrossTable { get; }
public bool ExistCrossTableTails { get; }
public bool IsEmpty { get; }
public ShardingRouteResult(List<ISqlRouteUnit> routeUnits,bool isEmpty,bool isCrossDataSource,bool isCrossTable,bool existCrossTableTails)
{
var routeUnitGroup = routeUnits.GroupBy(o=>o.DataSourceName);
RouteUnits = routeUnits;
var count = routeUnitGroup.Count();
IsEmpty =isEmpty;
IsCrossDataSource = isCrossDataSource;
IsCrossTable = isCrossTable;
ExistCrossTableTails=existCrossTableTails;
}
public override string ToString()
{
return string.Join(",", Environment.NewLine,RouteUnits.Select(o => o.ToString()));
}
}
}
//
// _isCrossDataSource = _sqlRouteUnits.Length > 1;
// _isCrossTable = _sqlRouteUnits.Any(o=>o.TableRouteResult.ReplaceTables.Count>1);
// _existCrossTableTails =_sqlRouteUnits.Any(o=>o.TableRouteResult.HasDifferentTail);

View File

@ -0,0 +1,49 @@
using System;
namespace ShardingCore.Core.VirtualRoutes
{
public sealed class TableRouteUnit
{
public TableRouteUnit(string dataSourceName, string tail,Type entityType)
{
DataSourceName = dataSourceName;
Tail = tail;
EntityType = entityType;
}
public string DataSourceName { get; }
public string Tail { get;}
public Type EntityType { get; }
private bool Equals(TableRouteUnit other)
{
return DataSourceName == other.DataSourceName && Tail == other.Tail && Equals(EntityType, other.EntityType);
}
public override bool Equals(object obj)
{
return ReferenceEquals(this, obj) || obj is TableRouteUnit other && Equals(other);
}
#if !EFCORE2
public override int GetHashCode()
{
return HashCode.Combine(DataSourceName, Tail, EntityType);
}
#endif
#if EFCORE2
public override int GetHashCode()
{
unchecked
{
var hashCode = (DataSourceName != null ? DataSourceName.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Tail != null ? Tail.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (EntityType != null ? EntityType.GetHashCode() : 0);
return hashCode;
}
}
#endif
}
}

View File

@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.QueryRouteManagers;
using ShardingCore.Core.QueryRouteManagers.Abstractions;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
@ -26,8 +23,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
/// <typeparam name="TKey"></typeparam>
public abstract class AbstractShardingFilterVirtualTableRoute<T, TKey> : AbstractVirtualTableRoute<T, TKey> where T : class
{
public ShardingRouteContext CurrentShardingRouteContext =>
ShardingContainer.GetService<IShardingRouteManager>().Current;
public ShardingRouteContext CurrentShardingRouteContext =>RouteShardingProvider.GetRequiredService<IShardingRouteManager>().Current;
/// <summary>
/// 启用提示路由
/// </summary>
@ -36,12 +32,21 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
/// 启用断言路由
/// </summary>
protected virtual bool EnableAssertRoute => false;
public override List<IPhysicTable> RouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable,bool isQuery)
/// <summary>
/// 路由是否忽略数据源
/// </summary>
protected virtual bool RouteIgnoreDataSource => true;
/// <summary>
/// 路由数据源和表后缀连接符
/// </summary>
protected virtual string RouteSeparator => ".";
public override List<TableRouteUnit> RouteWithPredicate(DataSourceRouteResult dataSourceRouteResult, IQueryable queryable,bool isQuery)
{
if (!isQuery)
{
//后拦截器
return DoRouteWithPredicate(allPhysicTables, queryable);
return DoRouteWithPredicate(dataSourceRouteResult, queryable);
}
//强制路由不经过断言
if (EnableHintRoute)
@ -50,47 +55,49 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
if (CurrentShardingRouteContext.TryGetMustTail<T>(out HashSet<string> mustTails) && mustTails.IsNotEmpty())
{
var physicTables = allPhysicTables.Where(o => mustTails.Contains(o.Tail)).ToList();
if (physicTables.IsEmpty()||physicTables.Count!=mustTails.Count)
var filterTails = GetTails().Where(o => mustTails.Contains(o)).ToList();
if (filterTails.IsEmpty()||filterTails.Count!=mustTails.Count)
throw new ShardingCoreException(
$" sharding route must error:[{EntityMetadata.EntityType.FullName}]-->[{string.Join(",",mustTails)}]");
return physicTables;
var shardingRouteUnits = dataSourceRouteResult.IntersectDataSources.SelectMany(dataSourceName=>filterTails.Select(tail=> new TableRouteUnit(dataSourceName,tail,typeof(T)))).ToList();
return shardingRouteUnits;
}
if (CurrentShardingRouteContext.TryGetHintTail<T>(out HashSet<string> hintTails) && hintTails.IsNotEmpty())
{
var physicTables = allPhysicTables.Where(o => hintTails.Contains(o.Tail)).ToList();
if (physicTables.IsEmpty()||physicTables.Count!=hintTails.Count)
var filterTails = GetTails().Where(o => hintTails.Contains(o)).ToList();
if (filterTails.IsEmpty()||filterTails.Count!=hintTails.Count)
throw new ShardingCoreException(
$" sharding route hint error:[{EntityMetadata.EntityType.FullName}]-->[{string.Join(",",hintTails)}]");
return GetFilterTableNames(allPhysicTables, physicTables);
var shardingRouteUnits = dataSourceRouteResult.IntersectDataSources.SelectMany(dataSourceName=>filterTails.Select(tail=> new TableRouteUnit(dataSourceName,tail,typeof(T)))).ToList();
return GetFilterTableTails(dataSourceRouteResult, shardingRouteUnits);
}
}
}
var filterPhysicTables = DoRouteWithPredicate(allPhysicTables,queryable);
return GetFilterTableNames(allPhysicTables, filterPhysicTables);
var filterPhysicTables = DoRouteWithPredicate(dataSourceRouteResult,queryable);
return GetFilterTableTails(dataSourceRouteResult, filterPhysicTables);
}
/// <summary>
/// 判断是调用全局过滤器还是调用内部断言
/// </summary>
/// <param name="allPhysicTables"></param>
/// <param name="filterPhysicTables"></param>
/// <param name="dataSourceRouteResult"></param>
/// <param name="shardingRouteUnits"></param>
/// <returns></returns>
private List<IPhysicTable> GetFilterTableNames(List<IPhysicTable> allPhysicTables, List<IPhysicTable> filterPhysicTables)
private List<TableRouteUnit> GetFilterTableTails(DataSourceRouteResult dataSourceRouteResult, List<TableRouteUnit> shardingRouteUnits)
{
if (UseAssertRoute)
{
//最后处理断言
ProcessAssertRoutes(allPhysicTables, filterPhysicTables);
return filterPhysicTables;
ProcessAssertRoutes(dataSourceRouteResult, shardingRouteUnits);
return shardingRouteUnits;
}
else
{
//后拦截器
return AfterPhysicTableFilter(allPhysicTables, filterPhysicTables);
return AfterShardingRouteUnitFilter(dataSourceRouteResult, shardingRouteUnits);
}
}
@ -99,7 +106,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
out ICollection<ITableRouteAssert> routeAsserts) &&
routeAsserts.IsNotEmpty();
private void ProcessAssertRoutes(List<IPhysicTable> allPhysicTables,List<IPhysicTable> filterPhysicTables)
private void ProcessAssertRoutes(DataSourceRouteResult dataSourceRouteResult,List<TableRouteUnit> shardingRouteUnits)
{
if (UseAssertRoute)
{
@ -107,24 +114,33 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
foreach (var routeAssert in routeAsserts)
{
routeAssert.Assert(allPhysicTables, filterPhysicTables);
routeAssert.Assert(dataSourceRouteResult,GetTails(), shardingRouteUnits);
}
}
}
}
protected abstract List<IPhysicTable> DoRouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable);
protected abstract List<TableRouteUnit> DoRouteWithPredicate(DataSourceRouteResult dataSourceRouteResult, IQueryable queryable);
/// <summary>
/// 物理表过滤后
/// </summary>
/// <param name="allPhysicTables">所有的物理表</param>
/// <param name="filterPhysicTables">过滤后的物理表</param>
/// <param name="dataSourceRouteResult">所有的数据源</param>
/// <param name="shardingRouteUnits">所有的物理表</param>
/// <returns></returns>
protected virtual List<IPhysicTable> AfterPhysicTableFilter(List<IPhysicTable> allPhysicTables, List<IPhysicTable> filterPhysicTables)
protected virtual List<TableRouteUnit> AfterShardingRouteUnitFilter(DataSourceRouteResult dataSourceRouteResult, List<TableRouteUnit> shardingRouteUnits)
{
return filterPhysicTables;
return shardingRouteUnits;
}
protected string FormatTableRouteWithDataSource(string dataSourceName, string tableTail)
{
if (RouteIgnoreDataSource)
{
return tableTail;
}
return $"{dataSourceName}{RouteSeparator}{tableTail}";
}
}
}

View File

@ -1,4 +1,3 @@
using ShardingCore.Core.PhysicTables;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
using ShardingCore.Utils;
@ -7,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
@ -18,16 +18,27 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
*/
public abstract class AbstractShardingOperatorVirtualTableRoute<TEntity, TKey> : AbstractShardingFilterVirtualTableRoute<TEntity, TKey> where TEntity : class
{
protected override List<IPhysicTable> DoRouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable)
/// <summary>
///
/// </summary>
/// <param name="dataSourceRouteResult"></param>
/// <param name="allPhysicTables"></param>
/// <param name="queryable"></param>
/// <returns></returns>
protected override List<TableRouteUnit> DoRouteWithPredicate(DataSourceRouteResult dataSourceRouteResult, IQueryable queryable)
{
//获取路由后缀表达式
var routeParseExpression = ShardingUtil.GetRouteParseExpression(queryable, EntityMetadata, GetRouteFilter,true);
//表达式缓存编译
// var filter =CachingCompile(routeParseExpression);
var filter =routeParseExpression.GetRoutePredicate();
//通过编译结果进行过滤
var physicTables = allPhysicTables.Where(o => filter(o.Tail)).ToList();
return physicTables;
var sqlRouteUnits = dataSourceRouteResult.IntersectDataSources.SelectMany(dataSourceName=>
GetTails()
.Where(o=>filter(FormatTableRouteWithDataSource(dataSourceName,o)))
.Select(tail=>new TableRouteUnit(dataSourceName,tail,typeof(TEntity)))
).ToList();
return sqlRouteUnits;
}
@ -60,19 +71,23 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
throw new NotImplementedException(shardingPropertyName);
}
public override IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey)
public override TableRouteUnit RouteWithValue(DataSourceRouteResult dataSourceRouteResult, object shardingKey)
{
if (dataSourceRouteResult.IntersectDataSources.Count !=1)
{
throw new ShardingCoreException($"more than one route match data source:{string.Join(",", dataSourceRouteResult.IntersectDataSources)}");
}
var shardingKeyToTail = ShardingKeyToTail(shardingKey);
var physicTables = allPhysicTables.Where(o => o.Tail== shardingKeyToTail).ToList();
if (physicTables.IsEmpty())
var filterTails = GetTails().Where(o => o== shardingKeyToTail).ToList();
if (filterTails.IsEmpty())
{
throw new ShardingCoreException($"sharding key route not match {EntityMetadata.EntityType} -> [{EntityMetadata.ShardingTableProperty.Name}] ->【{shardingKey}】 all tails ->[{string.Join(",", allPhysicTables.Select(o=>o.FullName))}]");
throw new ShardingCoreException($"sharding key route not match {EntityMetadata.EntityType} -> [{EntityMetadata.ShardingTableProperty.Name}] ->【{shardingKey}】 all tails ->[{string.Join(",", filterTails)}]");
}
if (physicTables.Count > 1)
throw new ShardingCoreException($"more than one route match table:{string.Join(",", physicTables.Select(o => $"[{o.FullName}]"))}");
return physicTables[0];
if (filterTails.Count > 1)
throw new ShardingCoreException($"more than one route match table:{string.Join(",", filterTails)}");
return new TableRouteUnit(dataSourceRouteResult.IntersectDataSources.First(), filterTails[0],typeof(TEntity));
}
}

View File

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

View File

@ -1,12 +1,15 @@
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Exceptions;
using ShardingCore.Sharding.MergeEngines.ParallelControl;
using ShardingCore.Sharding.PaginationConfigurations;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.ServiceProviders;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
using ShardingCore.Extensions;
using ShardingCore.Sharding.EntityQueryConfigurations;
using ShardingCore.Sharding.MergeEngines.Common.Abstractions;
namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
@ -20,15 +23,36 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce();
public IShardingEntityConfigOptions EntityConfigOptions { get; private set; }
public virtual void Initialize(EntityMetadata entityMetadata)
// public IShardingRouteConfigOptions RouteConfigOptions { get; private set; }
public PaginationMetadata PaginationMetadata { get; private set; }
public bool EnablePagination =>PaginationMetadata != null;
public EntityQueryMetadata EntityQueryMetadata { get; private set; }
public bool EnableEntityQuery =>EntityQueryMetadata != null;
public IShardingProvider RouteShardingProvider { get; private set;}
public virtual void Initialize(EntityMetadata entityMetadata,IShardingProvider shardingProvider)
{
if (!_doOnlyOnce.IsUnDo())
throw new ShardingCoreInvalidOperationException("already init");
RouteShardingProvider = shardingProvider;
EntityMetadata = entityMetadata;
// RouteConfigOptions =shardingProvider.GetService<IShardingRouteConfigOptions>();
var paginationConfiguration = CreatePaginationConfiguration();
if (paginationConfiguration!=null)
{
PaginationMetadata = new PaginationMetadata();
var paginationBuilder = new PaginationBuilder<T>(PaginationMetadata);
paginationConfiguration.Configure(paginationBuilder);
}
EntityConfigOptions =
ShardingContainer.GetRequiredShardingEntityConfigOption(entityMetadata.ShardingDbContextType);
var entityQueryConfiguration = CreateEntityQueryConfiguration();
if (entityQueryConfiguration != null)
{
EntityQueryMetadata = new EntityQueryMetadata();
var entityQueryBuilder = new EntityQueryBuilder<T>(EntityQueryMetadata);
entityQueryConfiguration.Configure(entityQueryBuilder);
}
}
@ -44,24 +68,24 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
/// <summary>
/// 根据表达式路由
/// </summary>
/// <param name="allPhysicTables"></param>
/// <param name="dataSourceRouteResult"></param>
/// <param name="queryable"></param>
/// <param name="isQuery"></param>
/// <returns></returns>
public abstract List<IPhysicTable> RouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable,bool isQuery);
public abstract List<TableRouteUnit> RouteWithPredicate(DataSourceRouteResult dataSourceRouteResult, IQueryable queryable,bool isQuery);
/// <summary>
/// 根据值路由
/// </summary>
/// <param name="allPhysicTables"></param>
/// <param name="dataSourceRouteResult"></param>
/// <param name="shardingKey"></param>
/// <returns></returns>
public abstract IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey);
public abstract TableRouteUnit RouteWithValue(DataSourceRouteResult dataSourceRouteResult, object shardingKey);
/// <summary>
/// 返回数据库现有的尾巴
/// </summary>
/// <returns></returns>
public abstract List<string> GetAllTails();
public abstract List<string> GetTails();
/// <summary>
/// 配置分表的一些信息

View File

@ -0,0 +1,15 @@
namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
{
/// <summary>
/// 可以追加尾巴
/// </summary>
public interface ITailAppendable
{
/// <summary>
/// 追加尾巴
/// </summary>
/// <param name="tail"></param>
/// <returns>是否添加成功</returns>
bool Append(string tail);
}
}

View File

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
using ShardingCore.Sharding.EntityQueryConfigurations;
using ShardingCore.Sharding.PaginationConfigurations;
@ -25,25 +25,43 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes
/// <summary>
/// 根据查询条件路由返回物理表
/// </summary>
/// <param name="allPhysicTables"></param>
/// <param name="dataSourceRouteResult"></param>
/// <param name="queryable"></param>
/// <param name="isQuery"></param>
/// <returns></returns>
List<IPhysicTable> RouteWithPredicate(List<IPhysicTable> allPhysicTables,IQueryable queryable,bool isQuery);
List<TableRouteUnit> RouteWithPredicate(DataSourceRouteResult dataSourceRouteResult,IQueryable queryable,bool isQuery);
/// <summary>
/// 根据值进行路由
/// </summary>
/// <param name="allPhysicTables"></param>
/// <param name="dataSourceRouteResult"></param>
/// <param name="shardingKey"></param>
/// <returns></returns>
IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey);
TableRouteUnit RouteWithValue(DataSourceRouteResult dataSourceRouteResult, object shardingKey);
/// <summary>
/// 获取所有的目前数据库存在的尾巴,仅启动时调用
/// get all tails in the db
/// </summary>
/// <returns></returns>
List<string> GetAllTails();
List<string> GetTails();
/// <summary>
/// 分页配置
/// </summary>
PaginationMetadata PaginationMetadata { get; }
/// <summary>
/// 是否启用智能分页
/// </summary>
bool EnablePagination {get; }// PaginationMetadata != null;
/// <summary>
/// 查询配置
/// </summary>
EntityQueryMetadata EntityQueryMetadata { get; }
/// <summary>
/// 是否启用表达式分片配置
/// </summary>
bool EnableEntityQuery { get; }
}

Some files were not shown because too many files have changed in this diff Show More