完成efcore 5.x的启动新增表结构和独立新增表结构
This commit is contained in:
parent
06d9e8f7a7
commit
b052861b9d
|
@ -25,7 +25,7 @@ namespace Sample.SqlServer.Controllers
|
|||
public async Task<IActionResult> Get()
|
||||
{
|
||||
var result = await _virtualDbContext.Set<SysUserMod>().ToShardingListAsync();
|
||||
var result1 = await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id=="2").ToShardingListAsync();
|
||||
var result1 = await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id=="2"||o.Id=="3").ToShardingListAsync();
|
||||
return Ok(result1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Sample.SqlServer.Domain.Entities;
|
||||
using ShardingCore;
|
||||
using ShardingCore.DbContexts.VirtualDbContexts;
|
||||
using ShardingCore.Extensions;
|
||||
|
||||
namespace Sample.SqlServer
|
||||
{
|
||||
|
@ -19,5 +24,30 @@ namespace Sample.SqlServer
|
|||
shardingBootstrapper.Start();
|
||||
return app;
|
||||
}
|
||||
|
||||
public static void DbSeed(this IApplicationBuilder app)
|
||||
{
|
||||
using (var scope=app.ApplicationServices.CreateScope())
|
||||
{
|
||||
var virtualDbContext =scope.ServiceProvider.GetService<IVirtualDbContext>();
|
||||
if (!virtualDbContext.Set<SysUserMod>().ShardingAny())
|
||||
{
|
||||
var ids = Enumerable.Range(1, 1000);
|
||||
var userMods = new List<SysUserMod>();
|
||||
foreach (var id in ids)
|
||||
{
|
||||
userMods.Add(new SysUserMod()
|
||||
{
|
||||
Id = id.ToString(),
|
||||
Age = id,
|
||||
Name = $"name_{id}",
|
||||
});
|
||||
}
|
||||
|
||||
virtualDbContext.InsertRange(userMods);
|
||||
virtualDbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,19 +4,19 @@ using System.Linq;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Sample.SqlServer.Domain.Maps;
|
||||
using ShardingCore.DbContexts.ShardingDbContexts;
|
||||
|
||||
namespace Sample.SqlServer.DbContexts
|
||||
{
|
||||
public class DefaultDbContext: DbContext
|
||||
public class DefaultTableDbContext: AbstractShardingTableDbContext
|
||||
{
|
||||
public DefaultDbContext(DbContextOptions<DefaultDbContext> options):base(options)
|
||||
public DefaultTableDbContext(ShardingDbContextOptions shardingDbContextOptions):base(shardingDbContextOptions)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
protected override void OnShardingModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
modelBuilder.ApplyConfiguration(new SysUserModMap());
|
||||
modelBuilder.ApplyConfiguration(new SysTestMap());
|
||||
}
|
|
@ -24,7 +24,7 @@ namespace Sample.SqlServer
|
|||
{
|
||||
o.EnsureCreatedWithOutShardingTable = true;
|
||||
o.CreateShardingTableOnStart = true;
|
||||
o.AddShardingDbContext<DefaultDbContext>("conn1", "Data Source=localhost;Initial Catalog=ShardingCoreDB123;Integrated Security=True", dbConfig =>
|
||||
o.AddShardingDbContextWithShardingTable<DefaultTableDbContext>("conn1", "Data Source=localhost;Initial Catalog=ShardingCoreDB123;Integrated Security=True", dbConfig =>
|
||||
{
|
||||
dbConfig.AddShardingTableRoute<SysUserModVirtualRoute>();
|
||||
});
|
||||
|
@ -46,6 +46,7 @@ namespace Sample.SqlServer
|
|||
app.UseRouting();
|
||||
|
||||
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
|
||||
app.DbSeed();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
|
||||
using ShardingCore.DbContexts.ShardingDbContexts;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Helpers;
|
||||
|
@ -21,7 +22,22 @@ namespace ShardingCore
|
|||
{
|
||||
private readonly IDictionary<string, ShardingConfigEntry> _shardingConfigs = new Dictionary<string, ShardingConfigEntry>();
|
||||
|
||||
public void AddShardingDbContext<TContext>(string connectKey, string connectString, Action<ShardingDbConfigOptions> func) where TContext : DbContext
|
||||
|
||||
public void AddShardingDbContext<TContext>(string connectKey, string connectString) where TContext : DbContext
|
||||
{
|
||||
if (_shardingConfigs.ContainsKey(connectKey))
|
||||
{
|
||||
throw new ArgumentException($"same connect key:[{connectKey}]");
|
||||
}
|
||||
|
||||
ShardingCoreHelper.CheckContextConstructors<TContext>();
|
||||
var creator = ShardingCoreHelper.CreateActivator<TContext>();
|
||||
var config = new ShardingConfigEntry(connectKey, connectString, creator, typeof(TContext), null);
|
||||
_shardingConfigs.Add(connectKey, config);
|
||||
}
|
||||
|
||||
|
||||
public void AddShardingDbContextWithShardingTable<TContext>(string connectKey, string connectString, Action<ShardingDbConfigOptions> func) where TContext : AbstractShardingTableDbContext
|
||||
{
|
||||
if (_shardingConfigs.ContainsKey(connectKey))
|
||||
{
|
||||
|
@ -34,11 +50,6 @@ namespace ShardingCore
|
|||
_shardingConfigs.Add(connectKey, config);
|
||||
}
|
||||
|
||||
public void AddShardingDbContext<T>(string connectKey, string connectString) where T : DbContext
|
||||
{
|
||||
AddShardingDbContext<T>(connectKey, connectString, null);
|
||||
}
|
||||
|
||||
|
||||
private readonly Dictionary<Type, Type> _virtualRoutes = new Dictionary<Type, Type>();
|
||||
public void AddDataSourceVirtualRoute<TRoute>() where TRoute : IDataSourceVirtualRoute
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ShardingCore.DbContexts.ShardingDbContexts
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/3/4 16:11:18
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public abstract class AbstractShardingDbContext : DbContext
|
||||
{
|
||||
public string Tail { get; }
|
||||
public Dictionary<Type, VirtualTableDbContextConfig> VirtualTableConfigs { get; }
|
||||
|
||||
protected AbstractShardingDbContext(ShardingDbContextOptions options)
|
||||
{
|
||||
Tail = options.Tail;
|
||||
VirtualTableConfigs = options.VirtualTableDbContextConfigs.ToDictionary(o => o.ShardingEntityType, o => o);
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
OnShardingModelCreating(modelBuilder);
|
||||
OnModelCreatingAfter(modelBuilder);
|
||||
}
|
||||
|
||||
protected abstract void OnShardingModelCreating(ModelBuilder modelBuilder);
|
||||
|
||||
protected virtual void OnModelCreatingAfter(ModelBuilder modelBuilder)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(Tail))
|
||||
{
|
||||
var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => VirtualTableConfigs.ContainsKey(o.ClrType));
|
||||
foreach (var entityType in mutableEntityTypes)
|
||||
{
|
||||
var virtualTableConfig = VirtualTableConfigs[entityType.ClrType];
|
||||
var shardingEntity = virtualTableConfig.ShardingEntityType;
|
||||
var tailPrefix = virtualTableConfig.TailPrefix;
|
||||
var entity = modelBuilder.Entity(shardingEntity);
|
||||
var tableName = virtualTableConfig.OriginalTableName;
|
||||
if (string.IsNullOrWhiteSpace(tableName))
|
||||
throw new ArgumentNullException($"{shardingEntity}: not found original table name。");
|
||||
#if DEBUG
|
||||
Console.WriteLine($"映射表:[tableName]-->[{tableName}{tailPrefix}{Tail}]");
|
||||
#endif
|
||||
entity.ToTable($"{tableName}{tailPrefix}{Tail}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Extensions;
|
||||
|
||||
namespace ShardingCore.DbContexts.ShardingDbContexts
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/3/4 16:11:18
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public abstract class AbstractShardingTableDbContext : DbContext
|
||||
{
|
||||
public string Tail { get; }
|
||||
public Dictionary<Type, VirtualTableDbContextConfig> VirtualTableConfigs { get; }
|
||||
|
||||
protected AbstractShardingTableDbContext(ShardingDbContextOptions options):base(options.DbContextOptions)
|
||||
{
|
||||
Tail = options.Tail;
|
||||
VirtualTableConfigs = options.VirtualTableDbContextConfigs.ToDictionary(o => o.ShardingEntityType, o => o);
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
OnShardingModelCreating(modelBuilder);
|
||||
OnModelCreatingAfter(modelBuilder);
|
||||
}
|
||||
|
||||
protected abstract void OnShardingModelCreating(ModelBuilder modelBuilder);
|
||||
|
||||
protected virtual void OnModelCreatingAfter(ModelBuilder modelBuilder)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(Tail))
|
||||
{
|
||||
if (VirtualTableConfigs.IsNotEmpty())
|
||||
{
|
||||
var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => VirtualTableConfigs.ContainsKey(o.ClrType));
|
||||
foreach (var entityType in mutableEntityTypes)
|
||||
{
|
||||
var virtualTableConfig = VirtualTableConfigs[entityType.ClrType];
|
||||
var shardingEntity = virtualTableConfig.ShardingEntityType;
|
||||
var tailPrefix = virtualTableConfig.TailPrefix;
|
||||
var entity = modelBuilder.Entity(shardingEntity);
|
||||
var tableName = virtualTableConfig.OriginalTableName;
|
||||
if (string.IsNullOrWhiteSpace(tableName))
|
||||
throw new ArgumentNullException($"{shardingEntity}: not found original table name。");
|
||||
#if DEBUG
|
||||
Console.WriteLine($"映射表:[tableName]-->[{tableName}{tailPrefix}{Tail}]");
|
||||
#endif
|
||||
entity.ToTable($"{tableName}{tailPrefix}{Tail}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ namespace ShardingCore.EFCores
|
|||
{
|
||||
public object Create(DbContext context)
|
||||
{
|
||||
if (context is AbstractShardingDbContext shardingDbContext)
|
||||
if (context is AbstractShardingTableDbContext shardingDbContext)
|
||||
{
|
||||
//当出现尾巴不一样,本次映射的数据库实体数目不一样就需要重建ef model
|
||||
var tail = shardingDbContext.Tail;
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace ShardingCore.Extensions
|
|||
{
|
||||
if (entityType == null)
|
||||
throw new ArgumentNullException(nameof(entityType));
|
||||
return typeof(AbstractShardingDbContext).IsAssignableFrom(entityType);
|
||||
return typeof(AbstractShardingTableDbContext).IsAssignableFrom(entityType);
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否基继承至IShardingEntity
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
|
||||
namespace ShardingCore.Extensions
|
||||
{
|
||||
public static class DbContextExtension
|
||||
{
|
||||
public static void RemoveDbContextRelationModelThatIsShardingTable(this DbContext dbContext)
|
||||
{
|
||||
var contextModel = dbContext.Model as Model;
|
||||
var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel;
|
||||
var valueTuples = contextModelRelationalModel.Tables.Where(o=>o.Value.EntityTypeMappings.Any(m=>m.EntityType.ClrType.IsShardingTable())).Select(o=>o.Key).ToList();
|
||||
for (int i = 0; i < valueTuples.Count; i++)
|
||||
{
|
||||
contextModelRelationalModel.Tables.Remove(valueTuples[i]);
|
||||
}
|
||||
}
|
||||
public static void RemoveDbContextRelationModelSaveOnlyThatIsShardingTable(this DbContext dbContext,Type shardingType)
|
||||
{
|
||||
var contextModel = dbContext.Model as Model;
|
||||
var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel;
|
||||
var valueTuples = contextModelRelationalModel.Tables.Where(o=> o.Value.EntityTypeMappings.All(m => m.EntityType.ClrType != shardingType)).Select(o=>o.Key).ToList();
|
||||
for (int i = 0; i < valueTuples.Count; i++)
|
||||
{
|
||||
contextModelRelationalModel.Tables.Remove(valueTuples[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,11 +25,49 @@ namespace ShardingCore.Extensions
|
|||
{
|
||||
return ShardingQueryable<T>.Create(source);
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否存在待条件
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="predicate"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> ShardingAnyAsync<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
return await ShardingQueryable<T>.Create(source.Where(predicate)).AnyAsync();
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否存在待条件
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="predicate"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static bool ShardingAny<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate)
|
||||
{
|
||||
return ShardingQueryable<T>.Create(source.Where(predicate)).Any();
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> ShardingAnyAsync<T>(this IQueryable<T> source)
|
||||
{
|
||||
return await ShardingQueryable<T>.Create(source).AnyAsync();
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static bool ShardingAny<T>(this IQueryable<T> source)
|
||||
{
|
||||
return ShardingQueryable<T>.Create(source).Any();
|
||||
}
|
||||
/// <summary>
|
||||
/// 分页
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes;
|
||||
using ShardingCore.DbContexts.ShardingDbContexts;
|
||||
|
||||
namespace ShardingCore
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ namespace ShardingCore
|
|||
*/
|
||||
public interface IShardingCoreOptions
|
||||
{
|
||||
void AddShardingDbContext<T>(string connectKey, string connectString, Action<ShardingDbConfigOptions> func) where T : DbContext;
|
||||
void AddShardingDbContextWithShardingTable<T>(string connectKey, string connectString, Action<ShardingDbConfigOptions> func) where T : AbstractShardingTableDbContext;
|
||||
|
||||
void AddShardingDbContext<T>(string connectKey, string connectString) where T : DbContext;
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace ShardingCore
|
|||
using var scope = _serviceProvider.CreateScope();
|
||||
var dbContextOptionsProvider = scope.ServiceProvider.GetService<IDbContextOptionsProvider>();
|
||||
using var context = _shardingDbContextFactory.Create(shardingConfig.ConnectKey,new ShardingDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(shardingConfig.ConnectKey), string.Empty, new List<VirtualTableDbContextConfig>()));
|
||||
var contextModel = context.Model as Model;
|
||||
context.RemoveDbContextRelationModelThatIsShardingTable();
|
||||
context.Database.EnsureCreated();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ using ShardingCore.DbContexts;
|
|||
using ShardingCore.DbContexts.ShardingDbContexts;
|
||||
using ShardingCore.DbContexts.VirtualDbContexts;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
|
||||
namespace ShardingCore.TableCreator
|
||||
{
|
||||
|
@ -55,6 +56,7 @@ namespace ShardingCore.TableCreator
|
|||
using (var dbContext = _shardingDbContextFactory.Create(connectKey,new ShardingDbContextOptions(dbContextOptionsProvider.GetDbContextOptions(connectKey), tail,
|
||||
new List<VirtualTableDbContextConfig>() {new VirtualTableDbContextConfig(shardingEntityType, virtualTable.GetOriginalTableName(), virtualTable.ShardingConfig.TailPrefix)})))
|
||||
{
|
||||
dbContext.RemoveDbContextRelationModelSaveOnlyThatIsShardingTable(shardingEntityType);
|
||||
var databaseCreator = dbContext.Database.GetService<IDatabaseCreator>() as RelationalDatabaseCreator;
|
||||
try
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue