多配置多租户多数据库demo
This commit is contained in:
parent
b8703c6421
commit
f2febbae4e
|
@ -57,7 +57,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShardingCoreBenchmark", "be
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShardingCoreBenchmark5x", "benchmarks\ShardingCoreBenchmark5x\ShardingCoreBenchmark5x.csproj", "{ED191305-AB19-4863-A48A-7BA4C21F467B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShardingCoreBenchmark5x", "benchmarks\ShardingCoreBenchmark5x\ShardingCoreBenchmark5x.csproj", "{ED191305-AB19-4863-A48A-7BA4C21F467B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.NoShardingMultiLevel", "samples\Sample.NoShardingMultiLevel\Sample.NoShardingMultiLevel.csproj", "{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.NoShardingMultiLevel", "samples\Sample.NoShardingMultiLevel\Sample.NoShardingMultiLevel.csproj", "{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.MultiConfig", "samples\Sample.MultiConfig\Sample.MultiConfig.csproj", "{D839D632-4AE4-4F75-8A2C-49EE029B0787}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -149,6 +151,10 @@ Global
|
||||||
{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}.Release|Any CPU.Build.0 = Release|Any CPU
|
{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{D839D632-4AE4-4F75-8A2C-49EE029B0787}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{D839D632-4AE4-4F75-8A2C-49EE029B0787}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{D839D632-4AE4-4F75-8A2C-49EE029B0787}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{D839D632-4AE4-4F75-8A2C-49EE029B0787}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -175,6 +181,7 @@ Global
|
||||||
{8CE5E8AF-DDB7-4989-8AA4-1D47E4226846} = {B458D737-33C5-4C10-9687-0BED2E7CD346}
|
{8CE5E8AF-DDB7-4989-8AA4-1D47E4226846} = {B458D737-33C5-4C10-9687-0BED2E7CD346}
|
||||||
{ED191305-AB19-4863-A48A-7BA4C21F467B} = {B458D737-33C5-4C10-9687-0BED2E7CD346}
|
{ED191305-AB19-4863-A48A-7BA4C21F467B} = {B458D737-33C5-4C10-9687-0BED2E7CD346}
|
||||||
{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734} = {EDF8869A-C1E1-491B-BC9F-4A33F4DE1C73}
|
{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734} = {EDF8869A-C1E1-491B-BC9F-4A33F4DE1C73}
|
||||||
|
{D839D632-4AE4-4F75-8A2C-49EE029B0787} = {EDF8869A-C1E1-491B-BC9F-4A33F4DE1C73}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {8C07A667-E8B4-43C7-8053-721584BAD291}
|
SolutionGuid = {8C07A667-E8B4-43C7-8053-721584BAD291}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
:start
|
:start
|
||||||
::定义版本
|
::定义版本
|
||||||
set EFCORE2=2.4.0.01-preview1
|
set EFCORE2=2.4.0.01-preview2
|
||||||
set EFCORE3=3.4.0.01-preview1
|
set EFCORE3=3.4.0.01-preview2
|
||||||
set EFCORE5=5.4.0.01-preview1
|
set EFCORE5=5.4.0.01-preview2
|
||||||
set EFCORE6=6.4.0.01-preview1
|
set EFCORE6=6.4.0.01-preview2
|
||||||
|
|
||||||
::删除所有bin与obj下的文件
|
::删除所有bin与obj下的文件
|
||||||
@echo off
|
@echo off
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Sample.MultiConfig.Domain.Entities;
|
||||||
|
|
||||||
|
namespace Sample.MultiConfig.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]/[action]")]
|
||||||
|
public class TestController:ControllerBase
|
||||||
|
{
|
||||||
|
private readonly MultiConfigDbContext _multiConfigDbContext;
|
||||||
|
|
||||||
|
public TestController(MultiConfigDbContext multiConfigDbContext)
|
||||||
|
{
|
||||||
|
_multiConfigDbContext = multiConfigDbContext;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Sample.MultiConfig.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class WeatherForecastController : ControllerBase
|
||||||
|
{
|
||||||
|
private static readonly string[] Summaries = new[]
|
||||||
|
{
|
||||||
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ILogger<WeatherForecastController> _logger;
|
||||||
|
|
||||||
|
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IEnumerable<WeatherForecast> Get()
|
||||||
|
{
|
||||||
|
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||||
|
{
|
||||||
|
Date = DateTime.Now.AddDays(index),
|
||||||
|
TemperatureC = Random.Shared.Next(-20, 55),
|
||||||
|
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Sample.MultiConfig.Domain.Entities
|
||||||
|
{
|
||||||
|
public class Order
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using Sample.MultiConfig.Domain.Entities;
|
||||||
|
|
||||||
|
namespace Sample.MultiConfig.Domain.Maps
|
||||||
|
{
|
||||||
|
public class OrderMap:IEntityTypeConfiguration<Order>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Order> builder)
|
||||||
|
{
|
||||||
|
builder.HasKey(o => o.Id);
|
||||||
|
builder.Property(o => o.Id).IsUnicode(false).HasMaxLength(50);
|
||||||
|
builder.Property(o => o.Name).HasMaxLength(100);
|
||||||
|
builder.ToTable(nameof(Order));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Sample.MultiConfig.Domain.Maps;
|
||||||
|
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||||
|
using ShardingCore.Sharding;
|
||||||
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
|
||||||
|
namespace Sample.MultiConfig
|
||||||
|
{
|
||||||
|
public class MultiConfigDbContext:AbstractShardingDbContext,IShardingTableDbContext
|
||||||
|
{
|
||||||
|
public MultiConfigDbContext(DbContextOptions<MultiConfigDbContext> options) : base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
modelBuilder.ApplyConfiguration(new OrderMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IRouteTail RouteTail { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
using Sample.MultiConfig.Domain.Entities;
|
||||||
|
using ShardingCore.Core.EntityMetadatas;
|
||||||
|
using ShardingCore.VirtualRoutes.Mods;
|
||||||
|
|
||||||
|
namespace Sample.MultiConfig
|
||||||
|
{
|
||||||
|
public class OrderIdModVirtualTableRoute:AbstractSimpleShardingModKeyStringVirtualTableRoute<Order>
|
||||||
|
{
|
||||||
|
public OrderIdModVirtualTableRoute() : base(2, 5)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Configure(EntityMetadataTableBuilder<Order> builder)
|
||||||
|
{
|
||||||
|
builder.ShardingProperty(o => o.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Sample.MultiConfig;
|
||||||
|
using Sample.MultiConfig.Middlewares;
|
||||||
|
using ShardingCore;
|
||||||
|
using ShardingCore.Bootstrapers;
|
||||||
|
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();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
app.Services.GetRequiredService<IShardingBootstrapper>().Start();
|
||||||
|
app.UseAuthorization();
|
||||||
|
app.UseMiddleware<TenantSelectMiddleware>();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:30769",
|
||||||
|
"sslPort": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"Sample.MultiConfig": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "weatherforecast",
|
||||||
|
"applicationUrl": "http://localhost:5138",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.1" />
|
||||||
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\ShardingCore\ShardingCore.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace Sample.MultiConfig
|
||||||
|
{
|
||||||
|
public class WeatherForecast
|
||||||
|
{
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureC { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||||
|
|
||||||
|
public string? Summary { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
|
@ -95,22 +95,26 @@ namespace ShardingCore.Bootstrapers
|
||||||
{
|
{
|
||||||
using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope())
|
using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
//var dataSourceName = _virtualDataSource.DefaultDataSourceName;
|
var configId = _virtualDataSourceManager.GetAllVirtualDataSources().First().ConfigId;
|
||||||
using var context =
|
using (_virtualDataSourceManager.CreateScope(configId))
|
||||||
(DbContext)serviceScope.ServiceProvider.GetService(_shardingDbContextType);
|
|
||||||
|
|
||||||
foreach (var entity in context.Model.GetEntityTypes())
|
|
||||||
{
|
{
|
||||||
var entityType = entity.ClrType;
|
//var dataSourceName = _virtualDataSource.DefaultDataSourceName;
|
||||||
_trackerManager.AddDbContextModel(entityType);
|
using var context =
|
||||||
//entity.GetAnnotation("")
|
(DbContext)serviceScope.ServiceProvider.GetService(_shardingDbContextType);
|
||||||
if (_entityConfigOptions.HasVirtualDataSourceRoute(entityType) ||
|
|
||||||
_entityConfigOptions.HasVirtualTableRoute(entityType))
|
foreach (var entity in context.Model.GetEntityTypes())
|
||||||
{
|
{
|
||||||
|
var entityType = entity.ClrType;
|
||||||
|
_trackerManager.AddDbContextModel(entityType);
|
||||||
|
//entity.GetAnnotation("")
|
||||||
|
if (_entityConfigOptions.HasVirtualDataSourceRoute(entityType) ||
|
||||||
|
_entityConfigOptions.HasVirtualTableRoute(entityType))
|
||||||
|
{
|
||||||
var entityMetadataInitializerType = typeof(EntityMetadataInitializer<,>).GetGenericType1(_shardingDbContextType, entityType);
|
var entityMetadataInitializerType = typeof(EntityMetadataInitializer<,>).GetGenericType1(_shardingDbContextType, entityType);
|
||||||
|
|
||||||
var entityMetadataInitializer = (IEntityMetadataInitializer)ShardingContainer.CreateInstanceWithInputParams(entityMetadataInitializerType, new EntityMetadataEnsureParams(entity));
|
var entityMetadataInitializer = (IEntityMetadataInitializer)ShardingContainer.CreateInstanceWithInputParams(entityMetadataInitializerType, new EntityMetadataEnsureParams(entity));
|
||||||
entityMetadataInitializer.Initialize();
|
entityMetadataInitializer.Initialize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (_shardingConfigOption.EnsureCreatedWithOutShardingTable)
|
//if (_shardingConfigOption.EnsureCreatedWithOutShardingTable)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -64,6 +65,13 @@ namespace ShardingCore.Core.ShardingConfigurations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode);
|
bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode);
|
||||||
ISet<ParallelTableGroupNode> GetParallelTableGroupNodes();
|
ISet<ParallelTableGroupNode> GetParallelTableGroupNodes();
|
||||||
|
Action<DbConnection, DbContextOptionsBuilder> ConnectionConfigure { get; }
|
||||||
|
Action<string, DbContextOptionsBuilder> ConnectionStringConfigure { get;}
|
||||||
|
|
||||||
|
|
||||||
|
public void UseShardingQuery(Action<string, DbContextOptionsBuilder> queryConfigure);
|
||||||
|
|
||||||
|
public void UseShardingTransaction(Action<DbConnection, DbContextOptionsBuilder> transactionConfigure);
|
||||||
}
|
}
|
||||||
public interface IShardingEntityConfigOptions<TShardingDbContext>: IShardingEntityConfigOptions where TShardingDbContext : DbContext, IShardingDbContext
|
public interface IShardingEntityConfigOptions<TShardingDbContext>: IShardingEntityConfigOptions where TShardingDbContext : DbContext, IShardingDbContext
|
||||||
{
|
{
|
||||||
|
@ -190,5 +198,17 @@ namespace ShardingCore.Core.ShardingConfigurations
|
||||||
{
|
{
|
||||||
return _parallelTables;
|
return _parallelTables;
|
||||||
}
|
}
|
||||||
|
public Action<DbConnection, DbContextOptionsBuilder> ConnectionConfigure { get; private set; }
|
||||||
|
public Action<string, DbContextOptionsBuilder> ConnectionStringConfigure { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
public void UseShardingQuery(Action<string, DbContextOptionsBuilder> queryConfigure)
|
||||||
|
{
|
||||||
|
ConnectionStringConfigure = queryConfigure ?? throw new ArgumentNullException(nameof(queryConfigure));
|
||||||
|
}
|
||||||
|
public void UseShardingTransaction(Action<DbConnection, DbContextOptionsBuilder> transactionConfigure)
|
||||||
|
{
|
||||||
|
ConnectionConfigure = transactionConfigure ?? throw new ArgumentNullException(nameof(transactionConfigure));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions
|
||||||
|
|
||||||
public virtual bool UseReadWriteSeparation()
|
public virtual bool UseReadWriteSeparation()
|
||||||
{
|
{
|
||||||
return ReadWriteSeparationConfigs.IsNotEmpty();
|
return ReadWriteSeparationConfigs!=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
using System;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data.Common;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using ShardingCore.Core.ShardingConfigurations;
|
using ShardingCore.Core.ShardingConfigurations;
|
||||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
|
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
|
||||||
using ShardingCore.Sharding.Abstractions;
|
using ShardingCore.Sharding.Abstractions;
|
||||||
using ShardingCore.Sharding.ParallelTables;
|
|
||||||
using ShardingCore.Sharding.ReadWriteConfigurations;
|
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||||
using ShardingCore.Sharding.ShardingComparision;
|
using ShardingCore.Sharding.ShardingComparision;
|
||||||
using ShardingCore.Sharding.ShardingComparision.Abstractions;
|
using ShardingCore.Sharding.ShardingComparision.Abstractions;
|
||||||
using ShardingCore.TableExists;
|
using ShardingCore.TableExists;
|
||||||
using ShardingCore.TableExists.Abstractions;
|
using ShardingCore.TableExists.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
|
namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
|
||||||
{
|
{
|
||||||
|
@ -22,6 +19,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
|
||||||
where TShardingDbContext : DbContext, IShardingDbContext
|
where TShardingDbContext : DbContext, IShardingDbContext
|
||||||
{
|
{
|
||||||
private readonly ShardingConfigOptions<TShardingDbContext> _options;
|
private readonly ShardingConfigOptions<TShardingDbContext> _options;
|
||||||
|
private readonly IShardingEntityConfigOptions<TShardingDbContext> _shardingEntityConfigOptions;
|
||||||
public override string ConfigId { get; }
|
public override string ConfigId { get; }
|
||||||
public override int Priority { get; }
|
public override int Priority { get; }
|
||||||
public override int MaxQueryConnectionsLimit { get; }
|
public override int MaxQueryConnectionsLimit { get; }
|
||||||
|
@ -39,6 +37,7 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
|
||||||
|
|
||||||
public SimpleVirtualDataSourceConfigurationParams(IServiceProvider serviceProvider,ShardingConfigOptions<TShardingDbContext> options)
|
public SimpleVirtualDataSourceConfigurationParams(IServiceProvider serviceProvider,ShardingConfigOptions<TShardingDbContext> options)
|
||||||
{
|
{
|
||||||
|
_shardingEntityConfigOptions = serviceProvider.GetService<IShardingEntityConfigOptions<TShardingDbContext>>();
|
||||||
_options = options;
|
_options = options;
|
||||||
ConfigId = options.ConfigId;
|
ConfigId = options.ConfigId;
|
||||||
Priority = options.Priority;
|
Priority = options.Priority;
|
||||||
|
@ -64,14 +63,36 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
|
||||||
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
|
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(string connectionString,
|
||||||
DbContextOptionsBuilder dbContextOptionsBuilder)
|
DbContextOptionsBuilder dbContextOptionsBuilder)
|
||||||
{
|
{
|
||||||
_options.ConnectionStringConfigure.Invoke(connectionString, dbContextOptionsBuilder);
|
if(_options.ConnectionStringConfigure==null&&_shardingEntityConfigOptions.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);
|
||||||
|
}
|
||||||
return dbContextOptionsBuilder;
|
return dbContextOptionsBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection,
|
public override DbContextOptionsBuilder UseDbContextOptionsBuilder(DbConnection dbConnection,
|
||||||
DbContextOptionsBuilder dbContextOptionsBuilder)
|
DbContextOptionsBuilder dbContextOptionsBuilder)
|
||||||
{
|
{
|
||||||
_options.ConnectionConfigure.Invoke(dbConnection, dbContextOptionsBuilder);
|
if (_options.ConnectionConfigure == null && _shardingEntityConfigOptions.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);
|
||||||
|
}
|
||||||
return dbContextOptionsBuilder;
|
return dbContextOptionsBuilder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace ShardingCore.DynamicDataSources
|
||||||
public class DataSourceInitializer<TShardingDbContext> : IDataSourceInitializer<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
|
public class DataSourceInitializer<TShardingDbContext> : IDataSourceInitializer<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
|
||||||
{
|
{
|
||||||
private readonly IShardingEntityConfigOptions<TShardingDbContext> _entityConfigOptions;
|
private readonly IShardingEntityConfigOptions<TShardingDbContext> _entityConfigOptions;
|
||||||
|
private readonly IVirtualDataSourceManager<TShardingDbContext> _virtualDataSourceManager;
|
||||||
private readonly IRouteTailFactory _routeTailFactory;
|
private readonly IRouteTailFactory _routeTailFactory;
|
||||||
private readonly IVirtualTableManager<TShardingDbContext> _virtualTableManager;
|
private readonly IVirtualTableManager<TShardingDbContext> _virtualTableManager;
|
||||||
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
|
private readonly IEntityMetadataManager<TShardingDbContext> _entityMetadataManager;
|
||||||
|
@ -30,12 +31,14 @@ namespace ShardingCore.DynamicDataSources
|
||||||
private readonly ILogger<DataSourceInitializer<TShardingDbContext>> _logger;
|
private readonly ILogger<DataSourceInitializer<TShardingDbContext>> _logger;
|
||||||
public DataSourceInitializer(
|
public DataSourceInitializer(
|
||||||
IShardingEntityConfigOptions<TShardingDbContext> entityConfigOptions,
|
IShardingEntityConfigOptions<TShardingDbContext> entityConfigOptions,
|
||||||
|
IVirtualDataSourceManager<TShardingDbContext> virtualDataSourceManager,
|
||||||
IRouteTailFactory routeTailFactory, IVirtualTableManager<TShardingDbContext> virtualTableManager,
|
IRouteTailFactory routeTailFactory, IVirtualTableManager<TShardingDbContext> virtualTableManager,
|
||||||
IEntityMetadataManager<TShardingDbContext> entityMetadataManager,
|
IEntityMetadataManager<TShardingDbContext> entityMetadataManager,
|
||||||
IShardingTableCreator<TShardingDbContext> shardingTableCreator,
|
IShardingTableCreator<TShardingDbContext> shardingTableCreator,
|
||||||
ILogger<DataSourceInitializer<TShardingDbContext>> logger)
|
ILogger<DataSourceInitializer<TShardingDbContext>> logger)
|
||||||
{
|
{
|
||||||
_entityConfigOptions = entityConfigOptions;
|
_entityConfigOptions = entityConfigOptions;
|
||||||
|
_virtualDataSourceManager = virtualDataSourceManager;
|
||||||
_routeTailFactory = routeTailFactory;
|
_routeTailFactory = routeTailFactory;
|
||||||
_virtualTableManager = virtualTableManager;
|
_virtualTableManager = virtualTableManager;
|
||||||
_entityMetadataManager = entityMetadataManager;
|
_entityMetadataManager = entityMetadataManager;
|
||||||
|
@ -47,36 +50,39 @@ namespace ShardingCore.DynamicDataSources
|
||||||
{
|
{
|
||||||
using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope())
|
using (var serviceScope = ShardingContainer.ServiceProvider.CreateScope())
|
||||||
{
|
{
|
||||||
using var context = serviceScope.ServiceProvider.GetService<TShardingDbContext>();
|
using (_virtualDataSourceManager.CreateScope(virtualDataSource.ConfigId))
|
||||||
if (_entityConfigOptions.EnsureCreatedWithOutShardingTable || !isOnStart)
|
|
||||||
EnsureCreated(virtualDataSource, context, dataSourceName);
|
|
||||||
var tableEnsureManager = virtualDataSource.ConfigurationParams.TableEnsureManager;
|
|
||||||
////获取数据库存在的所有的表
|
|
||||||
var existTables = tableEnsureManager?.GetExistTables(context, dataSourceName) ?? new HashSet<string>();
|
|
||||||
foreach (var entity in context.Model.GetEntityTypes())
|
|
||||||
{
|
{
|
||||||
var entityType = entity.ClrType;
|
using var context = serviceScope.ServiceProvider.GetService<TShardingDbContext>();
|
||||||
if (virtualDataSource.IsDefault(dataSourceName))
|
if (_entityConfigOptions.EnsureCreatedWithOutShardingTable || !isOnStart)
|
||||||
|
EnsureCreated(virtualDataSource, context, dataSourceName);
|
||||||
|
var tableEnsureManager = virtualDataSource.ConfigurationParams.TableEnsureManager;
|
||||||
|
////获取数据库存在的所有的表
|
||||||
|
var existTables = tableEnsureManager?.GetExistTables(context, dataSourceName) ?? new HashSet<string>();
|
||||||
|
foreach (var entity in context.Model.GetEntityTypes())
|
||||||
{
|
{
|
||||||
if (_entityMetadataManager.IsShardingTable(entityType))
|
var entityType = entity.ClrType;
|
||||||
|
if (virtualDataSource.IsDefault(dataSourceName))
|
||||||
{
|
{
|
||||||
var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
|
if (_entityMetadataManager.IsShardingTable(entityType))
|
||||||
//创建表
|
|
||||||
CreateDataTable( dataSourceName, virtualTable, existTables, isOnStart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_entityMetadataManager.IsShardingDataSource(entityType))
|
|
||||||
{
|
|
||||||
var virtualDataSourceRoute = virtualDataSource.GetRoute(entityType);
|
|
||||||
if (virtualDataSourceRoute.GetAllDataSourceNames().Contains(dataSourceName))
|
|
||||||
{
|
{
|
||||||
if (_entityMetadataManager.IsShardingTable(entityType))
|
var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
|
||||||
|
//创建表
|
||||||
|
CreateDataTable(dataSourceName, virtualTable, existTables, isOnStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_entityMetadataManager.IsShardingDataSource(entityType))
|
||||||
|
{
|
||||||
|
var virtualDataSourceRoute = virtualDataSource.GetRoute(entityType);
|
||||||
|
if (virtualDataSourceRoute.GetAllDataSourceNames().Contains(dataSourceName))
|
||||||
{
|
{
|
||||||
var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
|
if (_entityMetadataManager.IsShardingTable(entityType))
|
||||||
//创建表
|
{
|
||||||
CreateDataTable(dataSourceName, virtualTable, existTables, isOnStart);
|
var virtualTable = _virtualTableManager.GetVirtualTable(entityType);
|
||||||
|
//创建表
|
||||||
|
CreateDataTable(dataSourceName, virtualTable, existTables, isOnStart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,5 +254,6 @@ namespace ShardingCore
|
||||||
}
|
}
|
||||||
//public bool? EnableTableRouteCompileCache { get; set; }
|
//public bool? EnableTableRouteCompileCache { get; set; }
|
||||||
//public bool? EnableDataSourceRouteCompileCache { get; set; }
|
//public bool? EnableDataSourceRouteCompileCache { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue