efcore2x 也已经全面支持分库 后续开发针对分库的route和完成对应的readme
This commit is contained in:
parent
18cdbfea0e
commit
26f177aebb
|
@ -33,6 +33,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShardingCore.Test50_3x", "t
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.BulkConsole", "samples\Sample.BulkConsole\Sample.BulkConsole.csproj", "{2443CC8B-FB7D-47A7-9663-F3848BB30A36}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src2x", "src2x", "{F91949B0-02D5-4E3B-ACF4-AFA6C99A1E04}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShardingCore.2x", "src2x\ShardingCore.2x\ShardingCore.2x.csproj", "{A07C597D-339D-4378-BE4C-A2AF7473340B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShardingCore.Test50_2x", "test\ShardingCore.Test50_2x\ShardingCore.Test50_2x.csproj", "{E4DAA43A-B64D-45CF-81B8-7B8FD338D686}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -83,6 +89,14 @@ Global
|
|||
{2443CC8B-FB7D-47A7-9663-F3848BB30A36}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2443CC8B-FB7D-47A7-9663-F3848BB30A36}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2443CC8B-FB7D-47A7-9663-F3848BB30A36}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A07C597D-339D-4378-BE4C-A2AF7473340B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A07C597D-339D-4378-BE4C-A2AF7473340B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A07C597D-339D-4378-BE4C-A2AF7473340B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A07C597D-339D-4378-BE4C-A2AF7473340B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E4DAA43A-B64D-45CF-81B8-7B8FD338D686}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E4DAA43A-B64D-45CF-81B8-7B8FD338D686}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E4DAA43A-B64D-45CF-81B8-7B8FD338D686}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E4DAA43A-B64D-45CF-81B8-7B8FD338D686}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -99,6 +113,8 @@ Global
|
|||
{1136B8C9-3539-42FA-97FD-CAA6F146FCF0} = {EDF8869A-C1E1-491B-BC9F-4A33F4DE1C73}
|
||||
{C0A59BB0-F0B8-4AC6-B192-0249E784FC88} = {CC2C88C0-65F2-445D-BE78-973B840FE281}
|
||||
{2443CC8B-FB7D-47A7-9663-F3848BB30A36} = {EDF8869A-C1E1-491B-BC9F-4A33F4DE1C73}
|
||||
{A07C597D-339D-4378-BE4C-A2AF7473340B} = {F91949B0-02D5-4E3B-ACF4-AFA6C99A1E04}
|
||||
{E4DAA43A-B64D-45CF-81B8-7B8FD338D686} = {CC2C88C0-65F2-445D-BE78-973B840FE281}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8C07A667-E8B4-43C7-8053-721584BAD291}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Sample.BulkConsole
|
|||
services.AddLogging();
|
||||
services.AddShardingDbContext<MyShardingDbContext, MyDbContext>(
|
||||
o => o.UseSqlServer("Data Source=localhost;Initial Catalog=MyOrderSharding;Integrated Security=True;"))
|
||||
.Begin(true)
|
||||
.Begin(true,true)
|
||||
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking))
|
||||
.AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection))
|
||||
.AddDefaultDataSource("ds0", "Data Source=localhost;Initial Catalog=MyOrderSharding;Integrated Security=True;")
|
||||
|
@ -64,7 +64,11 @@ namespace Sample.BulkConsole
|
|||
startNew.Restart();
|
||||
foreach (var keyValuePair in bulkShardingEnumerable)
|
||||
{
|
||||
keyValuePair.Key.BulkInsert(keyValuePair.Value.ToList());
|
||||
foreach (var valuePair in keyValuePair.Value)
|
||||
{
|
||||
valuePair.Key.BulkInsert(valuePair.Value.ToList());
|
||||
}
|
||||
|
||||
}
|
||||
startNew.Stop();
|
||||
Console.WriteLine($"订单总数:{i}条,myShardingDbContext.BulkInsert(orders)用时:{startNew.ElapsedMilliseconds}毫秒");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Sample.SqlServer3x.Domain.Maps;
|
||||
using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace Sample.SqlServer3x
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,5 @@ namespace Samples.AutoByDate.SqlServer.DbContexts
|
|||
modelBuilder.ApplyConfiguration(new TestLogByWeekMap());
|
||||
}
|
||||
|
||||
public override Type ShardingDbContextType => this.GetType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using ChronusJob.Jobs.Attributes;
|
|||
using Samples.AutoByDate.SqlServer.DbContexts;
|
||||
using Samples.AutoByDate.SqlServer.Domain.Entities;
|
||||
using ShardingCore.Core.PhysicTables;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualTables;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
using ShardingCore.TableCreator;
|
||||
|
||||
|
@ -17,31 +18,31 @@ namespace Samples.AutoByDate.SqlServer.Jobs
|
|||
*/
|
||||
public class AutoCreateTableByDay : IJob
|
||||
{
|
||||
///// <summary>
|
||||
///// 每天中午12点执行,启动的时候执行以下
|
||||
///// </summary>
|
||||
///// <param name="virtualTableManager"></param>
|
||||
///// <param name="tableCreator"></param>
|
||||
//[JobRun(Name = "定时创建分表组件", Cron = "0 0 12 * * ?", RunOnceOnStart = true)]
|
||||
/// <summary>
|
||||
/// 每天中午12点执行,启动的时候执行以下
|
||||
/// </summary>
|
||||
/// <param name="virtualTableManager"></param>
|
||||
/// <param name="tableCreator"></param>
|
||||
[JobRun(Name = "定时创建分表组件", Cron = "0 0 12 * * ?", RunOnceOnStart = true)]
|
||||
|
||||
//public void AutoCreateTable(IVirtualTableManager virtualTableManager, IShardingTableCreator tableCreator)
|
||||
//{
|
||||
// var virtualTable = virtualTableManager.GetVirtualTable<DefaultShardingDbContext, SysUserLogByDay>();
|
||||
// if (virtualTable == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// var now = DateTime.Now.Date.AddDays(1);
|
||||
// var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now);
|
||||
// try
|
||||
// {
|
||||
// virtualTableManager.AddPhysicTable<DefaultShardingDbContext>(virtualTable, new DefaultPhysicTable(virtualTable, tail));
|
||||
// tableCreator.CreateTable<DefaultShardingDbContext, SysUserLogByDay>(tail);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// //ignore
|
||||
// }
|
||||
//}
|
||||
public void AutoCreateTable(IVirtualTableManager<DefaultShardingDbContext> virtualTableManager, IShardingTableCreator<DefaultShardingDbContext> tableCreator)
|
||||
{
|
||||
var virtualTable = virtualTableManager.GetVirtualTable(typeof(SysUserLogByDay));
|
||||
if (virtualTable == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var now = DateTime.Now.Date.AddDays(1);
|
||||
var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now);
|
||||
try
|
||||
{
|
||||
virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, tail));
|
||||
tableCreator.CreateTable("ds0",typeof(SysUserLogByDay),tail);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,16 +35,20 @@ namespace Samples.AutoByDate.SqlServer
|
|||
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "Samples.AutoByDate.SqlServer", Version = "v1"}); });
|
||||
|
||||
services.AddShardingDbContext<DefaultShardingDbContext, DefaultTableDbContext>(
|
||||
o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx2;Integrated Security=True;")
|
||||
, op =>
|
||||
o => o.UseSqlServer(
|
||||
"Data Source=localhost;Initial Catalog=ShardingCoreDBxx2;Integrated Security=True;")
|
||||
).Begin(true)
|
||||
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr)
|
||||
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking))
|
||||
.AddShardingTransaction((connection, builder) =>
|
||||
builder.UseSqlServer(connection))
|
||||
.AddDefaultDataSource("ds0",
|
||||
"Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;")
|
||||
.AddShardingTable(o =>
|
||||
{
|
||||
op.EnsureCreatedWithOutShardingTable = true;
|
||||
op.CreateShardingTableOnStart = true;
|
||||
op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection),
|
||||
(conStr,builder) => builder.UseSqlServer(conStr));
|
||||
op.AddShardingTableRoute<SysUserLogByDayVirtualTableRoute>();
|
||||
op.AddShardingTableRoute<TestLogWeekVirtualRoute>();
|
||||
});
|
||||
o.AddShardingTableRoute<SysUserLogByDayVirtualTableRoute>();
|
||||
o.AddShardingTableRoute<TestLogWeekVirtualRoute>();
|
||||
}).End();
|
||||
services.AddChronusJob();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,27 @@ namespace ShardingCore.Core.PhysicTables
|
|||
return Equals((DefaultPhysicTable)obj);
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(OriginalName, Tail, EntityType);
|
||||
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
|
||||
|
||||
}
|
||||
}
|
|
@ -43,7 +43,7 @@ namespace ShardingCore.Core.VirtualDatabase
|
|||
/// <summary>
|
||||
/// 分表的原表名 original table name in db exclude tail
|
||||
/// </summary>
|
||||
public string OriginalTableName { get; set; }
|
||||
public string VirtualTableName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启动时是否建表 auto create table when start app
|
||||
|
|
|
@ -9,6 +9,7 @@ using System.Collections.Concurrent;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using ShardingCore.Core.VirtualDatabase;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
|
||||
|
||||
namespace ShardingCore.Core.VirtualTables
|
||||
|
@ -34,7 +35,7 @@ namespace ShardingCore.Core.VirtualTables
|
|||
/// <summary>
|
||||
/// 分表的配置
|
||||
/// </summary>
|
||||
public ShardingTableConfig ShardingConfig { get; }
|
||||
public ShardingEntityConfig ShardingConfig { get; }
|
||||
/// <summary>
|
||||
/// 分库配置
|
||||
/// </summary>
|
||||
|
@ -51,7 +52,7 @@ namespace ShardingCore.Core.VirtualTables
|
|||
{
|
||||
_virtualTableRoute = virtualTableRoute;
|
||||
EntityType = typeof(T);
|
||||
ShardingConfig = ShardingKeyUtil.Parse(EntityType);
|
||||
ShardingConfig = ShardingUtil.Parse(EntityType);
|
||||
var paginationConfiguration = virtualTableRoute.CreatePaginationConfiguration();
|
||||
if (paginationConfiguration != null)
|
||||
{
|
||||
|
@ -78,7 +79,7 @@ namespace ShardingCore.Core.VirtualTables
|
|||
shardingKeyValue = tableRouteConfig.GetShardingKeyValue();
|
||||
|
||||
if (tableRouteConfig.UseEntity())
|
||||
shardingKeyValue = tableRouteConfig.GetShardingEntity().GetPropertyValue(ShardingConfig.ShardingField);
|
||||
shardingKeyValue = tableRouteConfig.GetShardingEntity().GetPropertyValue(ShardingConfig.ShardingTableField);
|
||||
|
||||
if (shardingKeyValue == null)
|
||||
throw new ShardingCoreException(" route entity queryable or sharding key value is null ");
|
||||
|
@ -94,14 +95,14 @@ namespace ShardingCore.Core.VirtualTables
|
|||
return _physicTables.TryAdd(physicTable, null);
|
||||
}
|
||||
|
||||
public void SetOriginalTableName(string originalTableName)
|
||||
public void SetVirtualTableName(string originalTableName)
|
||||
{
|
||||
ShardingConfig.ShardingOriginalTable = originalTableName;
|
||||
ShardingConfig.VirtualTableName = originalTableName;
|
||||
}
|
||||
|
||||
public string GetVirtualTableName()
|
||||
{
|
||||
return ShardingConfig.ShardingOriginalTable;
|
||||
return ShardingConfig.VirtualTableName;
|
||||
}
|
||||
|
||||
IVirtualTableRoute IVirtualTable.GetVirtualRoute()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ShardingCore.Core.PhysicTables;
|
||||
using ShardingCore.Core.VirtualDatabase;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes;
|
||||
using ShardingCore.Sharding.PaginationConfigurations;
|
||||
|
@ -25,7 +26,7 @@ namespace ShardingCore.Core.VirtualTables
|
|||
/// <summary>
|
||||
/// 分表配置
|
||||
/// </summary>
|
||||
ShardingTableConfig ShardingConfig { get; }
|
||||
ShardingEntityConfig ShardingConfig { get; }
|
||||
/// <summary>
|
||||
/// 分页配置
|
||||
/// </summary>
|
||||
|
@ -60,7 +61,7 @@ namespace ShardingCore.Core.VirtualTables
|
|||
/// <see cref="ShardingBootstrapper"/>
|
||||
/// </summary>
|
||||
/// <param name="originalTableName"></param>
|
||||
void SetOriginalTableName(string originalTableName);
|
||||
void SetVirtualTableName(string originalTableName);
|
||||
/// <summary>
|
||||
/// 获取原始表名 get original table name
|
||||
/// </summary>
|
||||
|
|
|
@ -1,41 +1,41 @@
|
|||
using System;
|
||||
//using System;
|
||||
|
||||
namespace ShardingCore.Core.VirtualTables
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Wednesday, 16 December 2020 13:24:05
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
/// <summary>
|
||||
/// 分表配置 sharding config
|
||||
/// </summary>
|
||||
public class ShardingTableConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 分表类型 sharding entity type
|
||||
/// </summary>
|
||||
public Type ShardingEntityType { get; set; }
|
||||
//namespace ShardingCore.Core.VirtualTables
|
||||
//{
|
||||
///*
|
||||
//* @Author: xjm
|
||||
//* @Description:
|
||||
//* @Date: Wednesday, 16 December 2020 13:24:05
|
||||
//* @Email: 326308290@qq.com
|
||||
//*/
|
||||
// /// <summary>
|
||||
// /// 分表配置 sharding config
|
||||
// /// </summary>
|
||||
// public class ShardingTableConfig
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// 分表类型 sharding entity type
|
||||
// /// </summary>
|
||||
// public Type ShardingEntityType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分表字段 sharding field
|
||||
/// </summary>
|
||||
public string ShardingField { get; set; }
|
||||
// /// <summary>
|
||||
// /// 分表字段 sharding field
|
||||
// /// </summary>
|
||||
// public string ShardingField { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分表的原表名 original table name in db exclude tail
|
||||
/// </summary>
|
||||
public string ShardingOriginalTable { get; set; }
|
||||
// /// <summary>
|
||||
// /// 分表的原表名 original table name in db exclude tail
|
||||
// /// </summary>
|
||||
// public string ShardingOriginalTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启动时是否建表 auto create table when start app
|
||||
/// </summary>
|
||||
public bool? AutoCreateTable { get; set; }
|
||||
// /// <summary>
|
||||
// /// 启动时是否建表 auto create table when start app
|
||||
// /// </summary>
|
||||
// public bool? AutoCreateTable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分表尾巴后缀 table sharding tail prefix
|
||||
/// </summary>
|
||||
public string TailPrefix { get; set; } = "_";
|
||||
}
|
||||
}
|
||||
// /// <summary>
|
||||
// /// 分表尾巴后缀 table sharding tail prefix
|
||||
// /// </summary>
|
||||
// public string TailPrefix { get; set; } = "_";
|
||||
// }
|
||||
//}
|
|
@ -30,7 +30,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes
|
|||
/// <returns>data source name</returns>
|
||||
string RouteWithValue(object shardingKeyValue);
|
||||
|
||||
ISet<string> GetAllDataSourceNames();
|
||||
List<string> GetAllDataSourceNames();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
|
|||
{
|
||||
var dataSourceMaps = new Dictionary<Type, ISet<string>>();
|
||||
var notShardingDataSourceEntityType = routeRuleContext.QueryEntities.FirstOrDefault(o => !o.IsShardingDataSource());
|
||||
//存在不分表的
|
||||
//存在不分库的
|
||||
if (notShardingDataSourceEntityType != null)
|
||||
dataSourceMaps.Add(notShardingDataSourceEntityType, new HashSet<string>() { _virtualDataSource.DefaultDataSourceName });
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
|
|||
protected override List<IPhysicTable> DoRouteWithPredicate(List<IPhysicTable> allPhysicTables, IQueryable queryable)
|
||||
{
|
||||
//获取所有需要路由的表后缀
|
||||
var filter = ShardingKeyUtil.GetRouteShardingTableFilter(queryable, ShardingKeyUtil.Parse(typeof(T)), ConvertToShardingKey, GetRouteToFilter);
|
||||
var filter = ShardingUtil.GetRouteShardingTableFilter(queryable, ShardingUtil.Parse(typeof(T)), ConvertToShardingKey, GetRouteToFilter);
|
||||
var physicTables = allPhysicTables.Where(o => filter(o.Tail)).ToList();
|
||||
return physicTables;
|
||||
}
|
||||
|
@ -43,8 +43,8 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions
|
|||
var physicTables = allPhysicTables.Where(o => o.Tail== shardingKeyToTail).ToList();
|
||||
if (physicTables.IsEmpty())
|
||||
{
|
||||
var routeConfig = ShardingKeyUtil.Parse(typeof(T));
|
||||
throw new ShardingKeyRouteNotMatchException($"{routeConfig.ShardingEntityType} -> [{routeConfig.ShardingField}] ->【{shardingKey}】 all tails ->[{string.Join(",", allPhysicTables.Select(o=>o.FullName))}]");
|
||||
var routeConfig = ShardingUtil.Parse(typeof(T));
|
||||
throw new ShardingKeyRouteNotMatchException($"{routeConfig.EntityType} -> [{routeConfig.ShardingTableField}] ->【{shardingKey}】 all tails ->[{string.Join(",", allPhysicTables.Select(o=>o.FullName))}]");
|
||||
}
|
||||
|
||||
if (physicTables.Count > 1)
|
||||
|
|
|
@ -12,9 +12,9 @@ namespace ShardingCore.EFCores
|
|||
* @Date: Saturday, 14 August 2021 10:17:43
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingDbSetSource:IDbSetSource
|
||||
{
|
||||
#if EFCORE5
|
||||
public class ShardingDbSetSource : IDbSetSource
|
||||
{
|
||||
|
||||
private static readonly MethodInfo _genericCreateSet
|
||||
= typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateSetFactory));
|
||||
|
@ -50,8 +50,11 @@ namespace ShardingCore.EFCores
|
|||
private static Func<DbContext, string, object> CreateSetFactory<TEntity>()
|
||||
where TEntity : class
|
||||
=> (c, name) => new ShardingInternalDbSet<TEntity>(c, name);
|
||||
}
|
||||
#endif
|
||||
#if EFCORE3
|
||||
public class ShardingDbSetSource:IDbSetSource
|
||||
{
|
||||
|
||||
private static readonly MethodInfo _genericCreateSet
|
||||
= typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateSetFactory));
|
||||
|
@ -78,7 +81,55 @@ namespace ShardingCore.EFCores
|
|||
private static Func<DbContext, object> CreateSetFactory<TEntity>()
|
||||
where TEntity : class
|
||||
=> c => new ShardingInternalDbSet<TEntity>(c);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EFCORE2
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public class ShardingDbSetSource : IDbSetSource, IDbQuerySource
|
||||
{
|
||||
private static readonly MethodInfo _genericCreateSet
|
||||
= typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateSetFactory));
|
||||
|
||||
private static readonly MethodInfo _genericCreateQuery
|
||||
= typeof(ShardingDbSetSource).GetTypeInfo().GetDeclaredMethod(nameof(CreateQueryFactory));
|
||||
|
||||
private readonly ConcurrentDictionary<Type, Func<DbContext, object>> _cache
|
||||
= new ConcurrentDictionary<Type, Func<DbContext, object>>();
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public virtual object Create(DbContext context, Type type)
|
||||
=> CreateCore(context, type, _genericCreateSet);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public virtual object CreateQuery(DbContext context, Type type)
|
||||
=> CreateCore(context, type, _genericCreateQuery);
|
||||
|
||||
private object CreateCore(DbContext context, Type type, MethodInfo createMethod)
|
||||
=> _cache.GetOrAdd(
|
||||
type,
|
||||
t => (Func<DbContext, object>)createMethod
|
||||
.MakeGenericMethod(t)
|
||||
.Invoke(null, null))(context);
|
||||
|
||||
private static Func<DbContext, object> CreateSetFactory<TEntity>()
|
||||
where TEntity : class
|
||||
=> c => new ShardingInternalDbSet<TEntity>(c);
|
||||
|
||||
private static Func<DbContext, DbQuery<TQuery>> CreateQueryFactory<TQuery>()
|
||||
where TQuery : class
|
||||
=> c => new ShardingInternalDbQuery<TQuery>(c);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
|
||||
namespace ShardingCore.EFCores
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/8/20 17:05:36
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
#if EFCORE2
|
||||
|
||||
public class ShardingInternalDbQuery<TQuery> : InternalDbQuery<TQuery> where TQuery : class
|
||||
{
|
||||
public ShardingInternalDbQuery(DbContext context) : base(context)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -55,6 +55,7 @@ namespace ShardingCore.EFCores
|
|||
/// any release. You should only use it directly in your code with extreme caution and knowing that
|
||||
/// doing so can result in application failures when updating to a new Entity Framework Core release.
|
||||
/// </summary>
|
||||
#if !EFCORE2
|
||||
public override async ValueTask<EntityEntry<TEntity>> AddAsync(
|
||||
TEntity entity,
|
||||
CancellationToken cancellationToken = default)
|
||||
|
@ -63,6 +64,15 @@ namespace ShardingCore.EFCores
|
|||
return await genericDbContext.AddAsync(entity, cancellationToken);
|
||||
|
||||
}
|
||||
#endif
|
||||
#if EFCORE2
|
||||
public override async Task<EntityEntry<TEntity>> AddAsync(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var genericDbContext = ((IShardingDbContext)_context).CreateGenericDbContext(entity);
|
||||
return await genericDbContext.AddAsync(entity, cancellationToken);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
|
||||
|
|
|
@ -69,11 +69,11 @@ namespace ShardingCore.EFCores
|
|||
|
||||
private void MappingToTable(Type clrType, ModelBuilder modelBuilder, string tail)
|
||||
{
|
||||
var shardingEntityConfig = ShardingKeyUtil.Parse(clrType);
|
||||
var shardingEntity = shardingEntityConfig.ShardingEntityType;
|
||||
var shardingEntityConfig = ShardingUtil.Parse(clrType);
|
||||
var shardingEntity = shardingEntityConfig.EntityType;
|
||||
var tailPrefix = shardingEntityConfig.TailPrefix;
|
||||
var entity = modelBuilder.Entity(shardingEntity);
|
||||
var tableName = shardingEntityConfig.ShardingOriginalTable;
|
||||
var tableName = shardingEntityConfig.VirtualTableName;
|
||||
if (string.IsNullOrWhiteSpace(tableName))
|
||||
throw new ArgumentNullException($"{shardingEntity}: not found original table name。");
|
||||
#if DEBUG
|
||||
|
|
|
@ -42,6 +42,8 @@ namespace ShardingCore.EFCores
|
|||
}
|
||||
|
||||
|
||||
#if !EFCORE2
|
||||
|
||||
public TResult ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
|
||||
{
|
||||
return _shardingQueryExecutor.ExecuteAsync<TResult>(_currentContext, query, cancellationToken);
|
||||
|
@ -62,6 +64,36 @@ namespace ShardingCore.EFCores
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if EFCORE2
|
||||
|
||||
|
||||
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(Expression query)
|
||||
{
|
||||
return _shardingQueryExecutor.ExecuteAsync<IAsyncEnumerable<TResult>>(_currentContext, query);
|
||||
}
|
||||
|
||||
public Task<TResult> ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken)
|
||||
{
|
||||
return _shardingQueryExecutor.ExecuteAsync<Task<TResult>>(_currentContext, query, cancellationToken);
|
||||
}
|
||||
|
||||
public Func<QueryContext, TResult> CreateCompiledQuery<TResult>(Expression query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Func<QueryContext, IAsyncEnumerable<TResult>> CreateCompiledAsyncEnumerableQuery<TResult>(Expression query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Func<QueryContext, Task<TResult>> CreateCompiledAsyncTaskQuery<TResult>(Expression query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ShardingCore.Exceptions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 21 December 2020 09:32:54
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingDataSourceNotFoundException:ShardingCoreException
|
||||
{
|
||||
public ShardingDataSourceNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
protected ShardingDataSourceNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public ShardingDataSourceNotFoundException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ShardingDataSourceNotFoundException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ShardingCore.Exceptions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 21 December 2020 09:32:54
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingOwnerNotFoundException:Exception
|
||||
{
|
||||
public ShardingOwnerNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
protected ShardingOwnerNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
|
||||
public ShardingOwnerNotFoundException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ShardingOwnerNotFoundException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -93,7 +93,7 @@ namespace ShardingCore.Extensions
|
|||
|
||||
public static ISet<Type> ParseQueryableRoute(this IQueryable queryable)
|
||||
{
|
||||
return ShardingKeyUtil.GetQueryEntitiesFilter(queryable);
|
||||
return ShardingUtil.GetQueryEntitiesFilter(queryable);
|
||||
}
|
||||
|
||||
public static T IfDo<T>(this T t, bool @if,Func<T,T> build)
|
||||
|
|
|
@ -133,6 +133,9 @@ var contextModelRelationalModel = contextModel.RelationalModel as RelationalMode
|
|||
var syncObject = modelSourceImpl.GetFieldValue("_syncObject");
|
||||
return syncObject;
|
||||
#endif
|
||||
#if EFCORE2
|
||||
return sLock;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
@ -60,7 +61,12 @@ namespace ShardingCore.Extensions
|
|||
|
||||
public static string ShardingPrint(this Expression expression)
|
||||
{
|
||||
#if !EFCORE2
|
||||
return expression.Print();
|
||||
#endif
|
||||
#if EFCORE2
|
||||
return expression.ToString();
|
||||
#endif
|
||||
}
|
||||
public static string ShardingPrint<T>(this IQueryable<T> queryable)
|
||||
{
|
||||
|
@ -75,110 +81,125 @@ namespace ShardingCore.Extensions
|
|||
/// <param name="shardingDbContext"></param>
|
||||
/// <param name="entities"></param>
|
||||
/// <returns></returns>
|
||||
public static IDictionary<DbContext, IEnumerable<TEntity>> BulkShardingEnumerable<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext,
|
||||
IEnumerable<TEntity> entities) where TShardingDbContext:DbContext,IShardingDbContext where TEntity : class
|
||||
public static Dictionary<string, Dictionary<DbContext, IEnumerable<TEntity>>> BulkShardingEnumerable<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext,
|
||||
IEnumerable<TEntity> entities) where TShardingDbContext : DbContext, IShardingDbContext where TEntity : class
|
||||
{
|
||||
var entityType = typeof(TEntity);
|
||||
var routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
|
||||
var virtualDataSource = ShardingContainer.GetService<IVirtualDataSource<TShardingDbContext>>();
|
||||
var dataSourceNames = new HashSet<string>();
|
||||
var dataSourceNames = new Dictionary<string, Dictionary<string, BulkDicEntry<TEntity>>>();
|
||||
var entitiesArray = entities as TEntity[] ?? entities.ToArray();
|
||||
if (!entityType.IsShardingDataSource())
|
||||
{
|
||||
dataSourceNames.Add(virtualDataSource.DefaultDataSourceName);
|
||||
var bulkDicEntries = new Dictionary<string, BulkDicEntry<TEntity>>();
|
||||
dataSourceNames.Add(virtualDataSource.DefaultDataSourceName, bulkDicEntries);
|
||||
|
||||
var isShardingTable = entityType.IsShardingTable();
|
||||
IVirtualTable virtualTable = null;
|
||||
IVirtualTableRoute virtualTableRoute = null;
|
||||
ISet<string> allTails = null;
|
||||
if (isShardingTable)
|
||||
{
|
||||
var virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDbContext>>();
|
||||
virtualTable = virtualTableManager.GetVirtualTable(entityType);
|
||||
virtualTableRoute = virtualTable.GetVirtualRoute();
|
||||
allTails = virtualTableRoute.GetAllTails().ToHashSet();
|
||||
}
|
||||
foreach (var entity in entitiesArray)
|
||||
{
|
||||
if (isShardingTable)
|
||||
BulkShardingTableEnumerable(shardingDbContext, virtualDataSource.DefaultDataSourceName, bulkDicEntries,
|
||||
routeTailFactory, virtualTable, virtualTableRoute, allTails, entity);
|
||||
else
|
||||
BulkNoShardingTableEnumerable(shardingDbContext, virtualDataSource.DefaultDataSourceName, bulkDicEntries,
|
||||
routeTailFactory, entity);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var virtualDataSourceRoute = virtualDataSource.GetRoute(entityType);
|
||||
var allDataSourceNames = virtualDataSourceRoute.GetAllDataSourceNames();
|
||||
var allDataSourceNames = virtualDataSourceRoute.GetAllDataSourceNames().ToHashSet();
|
||||
|
||||
var shardingEntityConfig = ShardingUtil.Parse(entityType);
|
||||
foreach (var entity in entities)
|
||||
var isShardingTable = entityType.IsShardingTable();
|
||||
IVirtualTable virtualTable = null;
|
||||
IVirtualTableRoute virtualTableRoute = null;
|
||||
ISet<string> allTails = null;
|
||||
if (isShardingTable)
|
||||
{
|
||||
entity.GetPropertyValue(shardingEntityConfig.ShardingDataSourceField)
|
||||
virtualDataSourceRoute.ShardingKeyToDataSourceName(entity)
|
||||
dataSourceNames.Add(dataSourceName);
|
||||
var virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDbContext>>();
|
||||
virtualTable = virtualTableManager.GetVirtualTable(entityType);
|
||||
virtualTableRoute = virtualTable.GetVirtualRoute();
|
||||
allTails = virtualTableRoute.GetAllTails().ToHashSet();
|
||||
}
|
||||
}
|
||||
if (!entityType.IsShardingDataSource())
|
||||
{
|
||||
virtualDataSource.
|
||||
var defaultDataSourceName = virtualDataSource.DefaultDataSourceName;
|
||||
if (!entityType.IsShardingTable())
|
||||
foreach (var entity in entitiesArray)
|
||||
{
|
||||
var routeTail = routeTailFactory.Create(string.Empty);
|
||||
var dbContext = shardingDbContext.GetDbContext(defaultDataSourceName, true, routeTail);
|
||||
return new Dictionary<DbContext, IEnumerable<TEntity>>()
|
||||
var shardingDataSourceValue = entity.GetPropertyValue(shardingEntityConfig.ShardingDataSourceField);
|
||||
if (shardingDataSourceValue == null)
|
||||
throw new InvalidOperationException($" etities has null value of sharding data source value");
|
||||
var shardingDataSourceName = virtualDataSourceRoute.ShardingKeyToDataSourceName(shardingDataSourceValue);
|
||||
if (!allDataSourceNames.Contains(shardingDataSourceName))
|
||||
throw new ShardingDataSourceNotFoundException(
|
||||
$" data source name :[{shardingDataSourceName}] all data source names:[{string.Join(",", allDataSourceNames)}]");
|
||||
if (!dataSourceNames.TryGetValue(shardingDataSourceName, out var bulkDicEntries))
|
||||
{
|
||||
{dbContext,entities }
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
var virtualTableManager = (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(shardingDbContext.ShardingDbContextType));
|
||||
var virtualTable = virtualTableManager.GetVirtualTable(entityType);
|
||||
|
||||
var virtualTableRoute = virtualTable.GetVirtualRoute();
|
||||
var hashSet = virtualTableRoute.GetAllTails().ToHashSet();
|
||||
var dic = new Dictionary<string, BulkDicEntry<TEntity>>();
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
var shardingKey = entity.GetPropertyValue(virtualTable.ShardingConfig.ShardingField);
|
||||
var tail = virtualTableRoute.ShardingKeyToTail(shardingKey);
|
||||
if (!hashSet.Contains(tail))
|
||||
throw new ShardingKeyRouteNotMatchException(
|
||||
$"Entity:{entityType.FullName},ShardingKey:{shardingKey},ShardingTail:{tail}");
|
||||
|
||||
var routeTail = routeTailFactory.Create(tail);
|
||||
var routeTailIdentity = routeTail.GetRouteTailIdentity();
|
||||
if (!dic.TryGetValue(routeTailIdentity, out var bulkDicEntry))
|
||||
{
|
||||
var dbContext = shardingDbContext.GetDbContext(defaultDataSourceName, true, routeTail);
|
||||
bulkDicEntry = new BulkDicEntry<TEntity>(dbContext, new LinkedList<TEntity>());
|
||||
dic.Add(routeTailIdentity, bulkDicEntry);
|
||||
}
|
||||
|
||||
bulkDicEntry.InnerEntities.AddLast(entity);
|
||||
bulkDicEntries = new Dictionary<string, BulkDicEntry<TEntity>>();
|
||||
dataSourceNames.Add(shardingDataSourceName, bulkDicEntries);
|
||||
}
|
||||
|
||||
return dic.Values.ToDictionary(o => o.InnerDbContext, o => o.InnerEntities.Select(t => t));
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!entityType.IsShardingTable())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
var virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
|
||||
var virtualTable = virtualTableManager.GetVirtualTable(shardingDbContext.ShardingDbContextType, entityType);
|
||||
|
||||
var virtualTableRoute = virtualTable.GetVirtualRoute();
|
||||
var hashSet = virtualTableRoute.GetAllTails().ToHashSet();
|
||||
var dic = new Dictionary<string, BulkDicEntry<TEntity>>();
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
var shardingKey = entity.GetPropertyValue(virtualTable.ShardingConfig.ShardingField);
|
||||
var tail = virtualTableRoute.ShardingKeyToTail(shardingKey);
|
||||
if (!hashSet.Contains(tail))
|
||||
throw new ShardingKeyRouteNotMatchException(
|
||||
$"Entity:{entityType.FullName},ShardingKey:{shardingKey},ShardingTail:{tail}");
|
||||
|
||||
var routeTail = routeTailFactory.Create(tail);
|
||||
var routeTailIdentity = routeTail.GetRouteTailIdentity();
|
||||
if (!dic.TryGetValue(routeTailIdentity, out var bulkDicEntry))
|
||||
if (isShardingTable)
|
||||
{
|
||||
var dbContext = shardingDbContext.GetDbContext(true, routeTail);
|
||||
bulkDicEntry = new BulkDicEntry<TEntity>(dbContext, new LinkedList<TEntity>());
|
||||
dic.Add(routeTailIdentity, bulkDicEntry);
|
||||
BulkShardingTableEnumerable(shardingDbContext, shardingDataSourceName, bulkDicEntries,
|
||||
routeTailFactory, virtualTable, virtualTableRoute, allTails, entity);
|
||||
}
|
||||
|
||||
bulkDicEntry.InnerEntities.AddLast(entity);
|
||||
else
|
||||
BulkNoShardingTableEnumerable(shardingDbContext, shardingDataSourceName, bulkDicEntries,
|
||||
routeTailFactory, entity);
|
||||
}
|
||||
|
||||
return dic.Values.ToDictionary(o => o.InnerDbContext, o => o.InnerEntities.Select(t => t));
|
||||
}
|
||||
|
||||
return dataSourceNames.ToDictionary(o => o.Key,
|
||||
o => o.Value.Values.ToDictionary(v => v.InnerDbContext, v => v.InnerEntities.Select(t => t)));
|
||||
}
|
||||
|
||||
private static void BulkShardingTableEnumerable<TShardingDbContext, TEntity>(TShardingDbContext shardingDbContext, string dataSourceName, Dictionary<string, BulkDicEntry<TEntity>> dataSourceBulkDicEntries,
|
||||
IRouteTailFactory routeTailFactory, IVirtualTable virtualTable,IVirtualTableRoute virtualTableRoute,ISet<string> allTails, TEntity entity)
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
where TEntity : class
|
||||
{
|
||||
var entityType = typeof(TEntity);
|
||||
|
||||
var shardingKey = entity.GetPropertyValue(virtualTable.ShardingConfig.ShardingTableField);
|
||||
var tail = virtualTableRoute.ShardingKeyToTail(shardingKey);
|
||||
if (!allTails.Contains(tail))
|
||||
throw new ShardingKeyRouteNotMatchException(
|
||||
$"entity:{entityType.FullName},sharding key:{shardingKey},sharding tail:{tail}");
|
||||
|
||||
var routeTail = routeTailFactory.Create(tail);
|
||||
var routeTailIdentity = routeTail.GetRouteTailIdentity();
|
||||
if (!dataSourceBulkDicEntries.TryGetValue(routeTailIdentity, out var bulkDicEntry))
|
||||
{
|
||||
var dbContext = shardingDbContext.GetDbContext(dataSourceName, true, routeTail);
|
||||
bulkDicEntry = new BulkDicEntry<TEntity>(dbContext, new LinkedList<TEntity>());
|
||||
dataSourceBulkDicEntries.Add(routeTailIdentity, bulkDicEntry);
|
||||
}
|
||||
|
||||
bulkDicEntry.InnerEntities.AddLast(entity);
|
||||
}
|
||||
private static void BulkNoShardingTableEnumerable<TShardingDbContext, TEntity>(TShardingDbContext shardingDbContext, string dataSourceName, Dictionary<string, BulkDicEntry<TEntity>> dataSourceBulkDicEntries, IRouteTailFactory routeTailFactory, TEntity entity)
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
where TEntity : class
|
||||
{
|
||||
var routeTail = routeTailFactory.Create(string.Empty);
|
||||
var routeTailIdentity = routeTail.GetRouteTailIdentity();
|
||||
if (!dataSourceBulkDicEntries.TryGetValue(routeTailIdentity, out var bulkDicEntry))
|
||||
{
|
||||
var dbContext = shardingDbContext.GetDbContext(dataSourceName, true, routeTail);
|
||||
bulkDicEntry = new BulkDicEntry<TEntity>(dbContext, new LinkedList<TEntity>());
|
||||
dataSourceBulkDicEntries.Add(routeTailIdentity, bulkDicEntry);
|
||||
}
|
||||
|
||||
bulkDicEntry.InnerEntities.AddLast(entity);
|
||||
}
|
||||
internal class BulkDicEntry<TEntity>
|
||||
{
|
||||
|
|
|
@ -104,6 +104,9 @@ namespace ShardingCore.Sharding
|
|||
}
|
||||
|
||||
|
||||
|
||||
#if !EFCORE2
|
||||
|
||||
public override ValueTask<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
|
||||
|
@ -113,6 +116,18 @@ namespace ShardingCore.Sharding
|
|||
{
|
||||
return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
|
||||
}
|
||||
#endif
|
||||
#if EFCORE2
|
||||
public override Task<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
|
||||
}
|
||||
|
||||
public override Task<EntityEntry> AddAsync(object entity, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
return CreateGenericDbContext(entity).AddAsync(entity, cancellationToken);
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void AddRange(params object[] entities)
|
||||
{
|
||||
|
@ -410,7 +425,12 @@ namespace ShardingCore.Sharding
|
|||
using(var tran= _shardingDbContextExecutor.BeginTransaction())
|
||||
{
|
||||
i = await _shardingDbContextExecutor.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
|
||||
await tran.CommitAsync(cancellationToken);
|
||||
#if EFCORE2
|
||||
tran.Commit();
|
||||
#endif
|
||||
#if !EFCORE2
|
||||
await tran.CommitAsync(cancellationToken);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -427,6 +447,7 @@ namespace ShardingCore.Sharding
|
|||
_shardingDbContextExecutor.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
#if !EFCORE2
|
||||
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
|
@ -434,6 +455,7 @@ namespace ShardingCore.Sharding
|
|||
|
||||
await base.DisposeAsync();
|
||||
}
|
||||
#endif
|
||||
|
||||
public IShardingTransaction BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified)
|
||||
{
|
||||
|
|
|
@ -21,7 +21,11 @@ namespace ShardingCore.Sharding.Abstractions
|
|||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public interface IShardingDbContextExecutor:IDisposable,IAsyncDisposable
|
||||
public interface IShardingDbContextExecutor : IDisposable
|
||||
#if !EFCORE2
|
||||
, IAsyncDisposable
|
||||
|
||||
#endif
|
||||
{
|
||||
IShardingTransaction CurrentShardingTransaction { get; }
|
||||
bool IsBeginTransaction { get; }
|
||||
|
@ -46,7 +50,7 @@ namespace ShardingCore.Sharding.Abstractions
|
|||
IEnumerable<DbContext> CreateExpressionDbContext<TEntity>(Expression<Func<TEntity, bool>> where)
|
||||
where TEntity : class;
|
||||
|
||||
IShardingTransaction BeginTransaction(IsolationLevel isolationLevel=IsolationLevel.Unspecified);
|
||||
IShardingTransaction BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified);
|
||||
|
||||
|
||||
Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
|
||||
|
|
|
@ -3,6 +3,10 @@ using System.Threading;
|
|||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
|
||||
#if EFCORE2
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
#endif
|
||||
|
||||
namespace ShardingCore.Sharding.Abstractions
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -24,6 +24,8 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
{
|
||||
_inMemoryStreamMergeAsyncEnumerator = inMemoryStreamMergeAsyncEnumerator;
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await _inMemoryStreamMergeAsyncEnumerator.DisposeAsync();
|
||||
|
@ -46,13 +48,32 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
|
||||
return _reverseEnumerator.MoveNext();
|
||||
}
|
||||
#endif
|
||||
#if EFCORE2
|
||||
public async Task<bool> MoveNext(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_first)
|
||||
{
|
||||
LinkedList<T> _reverseCollection = new LinkedList<T>();
|
||||
while (await _inMemoryStreamMergeAsyncEnumerator.MoveNext(cancellationToken))
|
||||
{
|
||||
_reverseCollection.AddFirst(_inMemoryStreamMergeAsyncEnumerator.GetCurrent());
|
||||
}
|
||||
|
||||
_reverseEnumerator = _reverseCollection.GetEnumerator();
|
||||
_first = false;
|
||||
}
|
||||
|
||||
return _reverseEnumerator.MoveNext();
|
||||
}
|
||||
#endif
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_first)
|
||||
{
|
||||
LinkedList<T> _reverseCollection = new LinkedList<T>();
|
||||
while ( _inMemoryStreamMergeAsyncEnumerator.MoveNext())
|
||||
while (_inMemoryStreamMergeAsyncEnumerator.MoveNext())
|
||||
{
|
||||
_reverseCollection.AddFirst(_inMemoryStreamMergeAsyncEnumerator.GetCurrent());
|
||||
}
|
||||
|
@ -91,7 +112,7 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
_inMemoryStreamMergeAsyncEnumerator.Dispose();
|
||||
_inMemoryStreamMergeAsyncEnumerator.Dispose();
|
||||
_reverseEnumerator.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,11 +56,21 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
return _mergeContext.SelectContext.SelectProperties.Where(o => !o.IsAggregateMethod)
|
||||
.Select(o => first.GetValueByExpression(o.PropertyName)).ToList();
|
||||
}
|
||||
#if !EFCORE2
|
||||
public async ValueTask<bool> MoveNextAsync()
|
||||
#endif
|
||||
#if EFCORE2
|
||||
public async Task<bool> MoveNext(CancellationToken cancellationToken = new CancellationToken())
|
||||
#endif
|
||||
{
|
||||
if (_queue.IsEmpty())
|
||||
return false;
|
||||
#if !EFCORE2
|
||||
var hasNext = await SetCurrentValueAsync();
|
||||
#endif
|
||||
#if EFCORE2
|
||||
var hasNext = await SetCurrentValueAsync(cancellationToken);
|
||||
#endif
|
||||
if (hasNext)
|
||||
{
|
||||
CurrentGroupValues = _queue.IsEmpty() ? new List<object>(0) : GetCurrentGroupValues(_queue.Peek());
|
||||
|
@ -79,7 +89,12 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
|
||||
return true;
|
||||
}
|
||||
#if !EFCORE2
|
||||
private async ValueTask<bool> SetCurrentValueAsync()
|
||||
#endif
|
||||
#if EFCORE2
|
||||
private async Task<bool> SetCurrentValueAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
#endif
|
||||
{
|
||||
CurrentValue = default;
|
||||
var currentValues = new List<T>();
|
||||
|
@ -89,7 +104,12 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
currentValues.Add(current);
|
||||
var first = _queue.Poll();
|
||||
|
||||
#if !EFCORE2
|
||||
if (await first.MoveNextAsync())
|
||||
#endif
|
||||
#if EFCORE2
|
||||
if (await first.MoveNext(cancellationToken))
|
||||
#endif
|
||||
{
|
||||
_queue.Offer(first);
|
||||
}
|
||||
|
@ -203,6 +223,7 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
return CurrentValue;
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
|
@ -211,6 +232,7 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
await enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public void Reset()
|
||||
|
|
|
@ -45,7 +45,12 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
|
||||
_currentEnumerator = _queue.IsEmpty() ? _enumerators.FirstOrDefault() : _queue.Peek();
|
||||
}
|
||||
#if !EFCORE2
|
||||
public async ValueTask<bool> MoveNextAsync()
|
||||
#endif
|
||||
#if EFCORE2
|
||||
public async Task<bool> MoveNext(CancellationToken cancellationToken = new CancellationToken())
|
||||
#endif
|
||||
{
|
||||
if (_queue.IsEmpty())
|
||||
return false;
|
||||
|
@ -56,8 +61,14 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
}
|
||||
|
||||
var first = _queue.Poll();
|
||||
#if !EFCORE2
|
||||
|
||||
if (await first.MoveNextAsync())
|
||||
#endif
|
||||
#if EFCORE2
|
||||
|
||||
if (await first.MoveNext(cancellationToken))
|
||||
#endif
|
||||
{
|
||||
_queue.Offer(first);
|
||||
}
|
||||
|
@ -117,6 +128,7 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
return _currentEnumerator.GetCurrent();
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
|
@ -125,6 +137,7 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
await enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -38,9 +38,19 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
_orderValues = HasElement() ? GetCurrentOrderValues() : new List<IComparable>(0);
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
public async ValueTask<bool> MoveNextAsync()
|
||||
#endif
|
||||
#if EFCORE2
|
||||
public async Task<bool> MoveNext(CancellationToken cancellationToken = new CancellationToken())
|
||||
#endif
|
||||
{
|
||||
#if !EFCORE2
|
||||
var has = await _enumerator.MoveNextAsync();
|
||||
#endif
|
||||
#if EFCORE2
|
||||
var has = await _enumerator.MoveNext(cancellationToken);
|
||||
#endif
|
||||
SetOrderValues();
|
||||
return has;
|
||||
}
|
||||
|
@ -119,10 +129,12 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
{
|
||||
return _orderValues ?? new List<IComparable>(0);
|
||||
}
|
||||
#if !EFCORE2
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _enumerator.DisposeAsync();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
|
@ -31,19 +31,34 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
else
|
||||
_enumerator = new MultiOrderStreamMergeAsyncEnumerator<T>(_mergeContext, sources);
|
||||
}
|
||||
#if !EFCORE2
|
||||
public async ValueTask<bool> MoveNextAsync()
|
||||
#endif
|
||||
#if EFCORE2
|
||||
public async Task<bool> MoveNext(CancellationToken cancellationToken = new CancellationToken())
|
||||
#endif
|
||||
{
|
||||
//如果合并数据的时候不需要跳过也没有take多少那么就是直接next
|
||||
while (_skip.GetValueOrDefault() > this.realSkip)
|
||||
{
|
||||
#if !EFCORE2
|
||||
var has = await _enumerator.MoveNextAsync();
|
||||
#endif
|
||||
#if EFCORE2
|
||||
var has = await _enumerator.MoveNext(cancellationToken);
|
||||
#endif
|
||||
|
||||
realSkip++;
|
||||
if (!has)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !EFCORE2
|
||||
var next = await _enumerator.MoveNextAsync();
|
||||
#endif
|
||||
#if EFCORE2
|
||||
var next = await _enumerator.MoveNext(cancellationToken);
|
||||
#endif
|
||||
|
||||
if (next)
|
||||
{
|
||||
|
@ -111,9 +126,12 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
|
|||
{
|
||||
_enumerator.Dispose();
|
||||
}
|
||||
#if !EFCORE2
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return _enumerator.DisposeAsync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -43,6 +43,7 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
}
|
||||
return false;
|
||||
}
|
||||
#if !EFCORE2
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_asyncSource != null)
|
||||
|
@ -95,6 +96,7 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
return _syncSource.MoveNext();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
@ -104,5 +106,69 @@ namespace ShardingCore.Sharding.Enumerators
|
|||
}
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
#if EFCORE2
|
||||
public void Dispose()
|
||||
{
|
||||
_asyncSource.Dispose();
|
||||
}
|
||||
|
||||
public async Task<bool> MoveNext(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
if (skip)
|
||||
{
|
||||
skip = false;
|
||||
return null != SourceCurrent();
|
||||
}
|
||||
return await _asyncSource.MoveNext(cancellationToken);
|
||||
}
|
||||
public T Current => GetCurrent();
|
||||
public T ReallyCurrent => GetReallyCurrent();
|
||||
public bool HasElement()
|
||||
{
|
||||
return null != SourceCurrent();
|
||||
}
|
||||
|
||||
private T SourceCurrent()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (tryGetCurrentError)
|
||||
return default;
|
||||
return _asyncSource.Current;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
tryGetCurrentError = true;
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
private bool tryGetCurrentError = false;
|
||||
|
||||
public T GetCurrent()
|
||||
{
|
||||
if (skip)
|
||||
return default;
|
||||
if (_asyncSource != null) return SourceCurrent();
|
||||
if (_syncSource != null) return _syncSource.Current;
|
||||
return default;
|
||||
}
|
||||
public T GetReallyCurrent()
|
||||
{
|
||||
if (_asyncSource != null) return SourceCurrent();
|
||||
if (_syncSource != null) return _syncSource.Current;
|
||||
return default;
|
||||
}
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (skip)
|
||||
{
|
||||
skip = false;
|
||||
return null != _syncSource.Current;
|
||||
}
|
||||
return _syncSource.MoveNext();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -226,7 +226,12 @@ namespace ShardingCore.Sharding
|
|||
{
|
||||
foreach (var keyValuePair in dbContextCache.Value)
|
||||
{
|
||||
#if EFCORE2
|
||||
keyValuePair.Value.Database.UseTransaction(null);
|
||||
#endif
|
||||
#if !EFCORE2
|
||||
await keyValuePair.Value.Database.UseTransactionAsync(null, cancellationToken);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
this.CurrentShardingTransaction = null;
|
||||
|
@ -274,6 +279,7 @@ namespace ShardingCore.Sharding
|
|||
}
|
||||
|
||||
}
|
||||
#if !EFCORE2
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
|
@ -285,5 +291,6 @@ namespace ShardingCore.Sharding
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,9 @@ using ShardingCore.Sharding.Abstractions;
|
|||
using ShardingCore.Sharding.StreamMergeEngines;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
|
||||
using ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines;
|
||||
#if EFCORE2
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
#endif
|
||||
|
||||
namespace ShardingCore.Sharding.ShardingQueryExecutors
|
||||
{
|
||||
|
|
|
@ -13,14 +13,19 @@ namespace ShardingCore.Sharding.ShardingTransactions
|
|||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public interface IShardingTransaction:IDisposable,IAsyncDisposable
|
||||
public interface IShardingTransaction:IDisposable
|
||||
#if !EFCORE2
|
||||
,IAsyncDisposable
|
||||
#endif
|
||||
{
|
||||
bool IsBeginTransaction();
|
||||
void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified);
|
||||
void Use(string dataSourceName,DbContext dbContext);
|
||||
void Rollback();
|
||||
Task RollbackAsync(CancellationToken cancellationToken=new CancellationToken());
|
||||
void Commit();
|
||||
#if !EFCORE2
|
||||
Task RollbackAsync(CancellationToken cancellationToken = new CancellationToken());
|
||||
Task CommitAsync(CancellationToken cancellationToken = new CancellationToken());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace ShardingCore.Sharding.ShardingTransactions
|
|||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingTransaction: IShardingTransaction
|
||||
public class ShardingTransaction : IShardingTransaction
|
||||
{
|
||||
private readonly IShardingDbContextExecutor _shardingDbContextExecutor;
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace ShardingCore.Sharding.ShardingTransactions
|
|||
|
||||
private IsolationLevel isolationLevel = IsolationLevel.Unspecified;
|
||||
|
||||
private bool _isBeginTransaction=false;
|
||||
private bool _isBeginTransaction = false;
|
||||
|
||||
public ShardingTransaction(IShardingDbContextExecutor shardingDbContextExecutor)
|
||||
{
|
||||
|
@ -84,22 +84,6 @@ namespace ShardingCore.Sharding.ShardingTransactions
|
|||
this._shardingDbContextExecutor.ClearTransaction();
|
||||
}
|
||||
|
||||
public async Task RollbackAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
foreach (var dbContextTransaction in _dbContextTransactions)
|
||||
{
|
||||
try
|
||||
{
|
||||
await dbContextTransaction.Value.RollbackAsync(cancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"rollback error:[{e}]");
|
||||
}
|
||||
}
|
||||
await this._shardingDbContextExecutor.ClearTransactionAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
foreach (var dbContextTransaction in _dbContextTransactions)
|
||||
|
@ -116,7 +100,24 @@ namespace ShardingCore.Sharding.ShardingTransactions
|
|||
this._shardingDbContextExecutor.ClearTransaction();
|
||||
}
|
||||
|
||||
public async Task CommitAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
#if !EFCORE2
|
||||
|
||||
public async Task RollbackAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
foreach (var dbContextTransaction in _dbContextTransactions)
|
||||
{
|
||||
try
|
||||
{
|
||||
await dbContextTransaction.Value.RollbackAsync(cancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"rollback error:[{e}]");
|
||||
}
|
||||
}
|
||||
await this._shardingDbContextExecutor.ClearTransactionAsync(cancellationToken);
|
||||
}
|
||||
public async Task CommitAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
foreach (var dbContextTransaction in _dbContextTransactions)
|
||||
{
|
||||
|
@ -131,24 +132,6 @@ namespace ShardingCore.Sharding.ShardingTransactions
|
|||
}
|
||||
await this._shardingDbContextExecutor.ClearTransactionAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
foreach (var dbContextTransaction in _dbContextTransactions)
|
||||
{
|
||||
try
|
||||
{
|
||||
dbContextTransaction.Value.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"dispose error:[{e}]");
|
||||
}
|
||||
}
|
||||
_dbContextTransactions.Clear();
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
foreach (var dbContextTransaction in _dbContextTransactions)
|
||||
|
@ -164,5 +147,24 @@ namespace ShardingCore.Sharding.ShardingTransactions
|
|||
}
|
||||
_dbContextTransactions.Clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
foreach (var dbContextTransaction in _dbContextTransactions)
|
||||
{
|
||||
try
|
||||
{
|
||||
dbContextTransaction.Value.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"dispose error:[{e}]");
|
||||
}
|
||||
}
|
||||
_dbContextTransactions.Clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,22 @@ namespace ShardingCore.Sharding.StreamMergeEngines
|
|||
}
|
||||
|
||||
|
||||
#if !EFCORE2
|
||||
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
return new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync(cancellationToken)
|
||||
.GetAsyncEnumerator(cancellationToken);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if EFCORE2
|
||||
IAsyncEnumerator<T> IAsyncEnumerable<T>.GetEnumerator()
|
||||
{
|
||||
return ((IAsyncEnumerable<T>)new EnumeratorShardingQueryExecutor<T>(_mergeContext).ExecuteAsync())
|
||||
.GetEnumerator();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
|
|
|
@ -10,6 +10,9 @@ using ShardingCore.Exceptions;
|
|||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
|
||||
#if EFCORE2
|
||||
using Microsoft.EntityFrameworkCore.Extensions.Internal;
|
||||
#endif
|
||||
|
||||
namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.Abstractions
|
||||
{
|
||||
|
@ -30,7 +33,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
|
|||
public abstract IStreamMergeAsyncEnumerator<TEntity>[] GetDbStreamMergeAsyncEnumerators(bool async);
|
||||
public abstract IStreamMergeAsyncEnumerator<TEntity> GetStreamMergeAsyncEnumerator(IStreamMergeAsyncEnumerator<TEntity>[] streamsAsyncEnumerators);
|
||||
|
||||
public Task<StreamMergeAsyncEnumerator<TEntity>> AsyncQueryEnumerator(IQueryable<TEntity> queryable,bool async)
|
||||
public Task<StreamMergeAsyncEnumerator<TEntity>> AsyncQueryEnumerator(IQueryable<TEntity> queryable, bool async)
|
||||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
|
@ -43,7 +46,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
|
|||
}
|
||||
else
|
||||
{
|
||||
var enumerator = DoGetEnumerator(queryable);
|
||||
var enumerator = DoGetEnumerator(queryable);
|
||||
return new StreamMergeAsyncEnumerator<TEntity>(enumerator);
|
||||
|
||||
}
|
||||
|
@ -57,26 +60,33 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
|
|||
}
|
||||
public async Task<IAsyncEnumerator<TEntity>> DoGetAsyncEnumerator(IQueryable<TEntity> newQueryable)
|
||||
{
|
||||
#if !EFCORE2
|
||||
var enumator = newQueryable.AsAsyncEnumerable().GetAsyncEnumerator();
|
||||
await enumator.MoveNextAsync();
|
||||
return enumator;
|
||||
#endif
|
||||
#if EFCORE2
|
||||
var enumator = newQueryable.AsAsyncEnumerable().GetEnumerator();
|
||||
await enumator.MoveNext();
|
||||
return enumator;
|
||||
#endif
|
||||
}
|
||||
public IEnumerator<TEntity> DoGetEnumerator(IQueryable<TEntity> newQueryable)
|
||||
{
|
||||
var enumator = newQueryable.AsEnumerable().GetEnumerator();
|
||||
enumator.MoveNext();
|
||||
enumator.MoveNext();
|
||||
return enumator;
|
||||
}
|
||||
// public virtual IQueryable<TEntity> CreateAsyncExecuteQueryable(TableRouteResult tableRouteResult)
|
||||
// public virtual IQueryable<TEntity> CreateAsyncExecuteQueryable(RouteResult routeResult)
|
||||
// {
|
||||
// var shardingDbContext = StreamMergeContext.CreateDbContext(tableRouteResult);
|
||||
// var shardingDbContext = StreamMergeContext.CreateDbContext(routeResult);
|
||||
// var useOriginal = StreamMergeContext > 1;
|
||||
// DbContextQueryStore.TryAdd(tableRouteResult,shardingDbContext);
|
||||
// DbContextQueryStore.TryAdd(routeResult,shardingDbContext);
|
||||
// var newQueryable = (IQueryable<TEntity>)(useOriginal ? StreamMergeContext.GetReWriteQueryable() : StreamMergeContext.GetOriginalQueryable())
|
||||
// .ReplaceDbContextQueryable(shardingDbContext);
|
||||
// return newQueryable;
|
||||
// }
|
||||
|
||||
|
||||
public override IStreamMergeAsyncEnumerator<TEntity> GetShardingAsyncEnumerator(bool async,
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
|
|
|
@ -18,10 +18,10 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
|
|||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public abstract class AbstractEnumeratorStreamMergeEngine<TEntity>:IEnumeratorStreamMergeEngine<TEntity>
|
||||
public abstract class AbstractEnumeratorStreamMergeEngine<TEntity> : IEnumeratorStreamMergeEngine<TEntity>
|
||||
{
|
||||
public StreamMergeContext<TEntity> StreamMergeContext { get; }
|
||||
public ConcurrentDictionary<TableRouteResult,DbContext> DbContextQueryStore { get; }
|
||||
public ConcurrentDictionary<TableRouteResult, DbContext> DbContextQueryStore { get; }
|
||||
|
||||
public AbstractEnumeratorStreamMergeEngine(StreamMergeContext<TEntity> streamMergeContext)
|
||||
{
|
||||
|
@ -32,13 +32,23 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
|
|||
public abstract IStreamMergeAsyncEnumerator<TEntity> GetShardingAsyncEnumerator(bool async,
|
||||
CancellationToken cancellationToken = new CancellationToken());
|
||||
|
||||
#if !EFCORE2
|
||||
public IAsyncEnumerator<TEntity> GetAsyncEnumerator(
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
return GetShardingAsyncEnumerator(true,cancellationToken);
|
||||
}
|
||||
#endif
|
||||
|
||||
public IEnumerator<TEntity> GetEnumerator()
|
||||
#if EFCORE2
|
||||
IAsyncEnumerator<TEntity> IAsyncEnumerable<TEntity>.GetEnumerator()
|
||||
{
|
||||
return GetShardingAsyncEnumerator(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
public IEnumerator<TEntity> GetEnumerator()
|
||||
{
|
||||
return GetShardingAsyncEnumerator(false);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using ShardingCore.Core.VirtualDatabase;
|
||||
using ShardingCore.Core.VirtualRoutes;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
using ShardingCore.Exceptions;
|
||||
|
@ -17,12 +18,12 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
*/
|
||||
public class QueryableRouteShardingTableDiscoverVisitor<TKey> : ExpressionVisitor
|
||||
{
|
||||
private readonly ShardingTableConfig _shardingConfig;
|
||||
private readonly ShardingEntityConfig _shardingConfig;
|
||||
private readonly Func<object, TKey> _shardingKeyConvert;
|
||||
private readonly Func<TKey, ShardingOperatorEnum, Expression<Func<string, bool>>> _keyToTailWithFilter;
|
||||
private Expression<Func<string, bool>> _where = x => true;
|
||||
|
||||
public QueryableRouteShardingTableDiscoverVisitor(ShardingTableConfig shardingConfig, Func<object, TKey> shardingKeyConvert, Func<TKey, ShardingOperatorEnum, Expression<Func<string, bool>>> keyToTailWithFilter)
|
||||
public QueryableRouteShardingTableDiscoverVisitor(ShardingEntityConfig shardingConfig, Func<object, TKey> shardingKeyConvert, Func<TKey, ShardingOperatorEnum, Expression<Func<string, bool>>> keyToTailWithFilter)
|
||||
{
|
||||
_shardingConfig = shardingConfig;
|
||||
_shardingKeyConvert = shardingKeyConvert;
|
||||
|
@ -37,8 +38,8 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
private bool IsShardingKey(Expression expression)
|
||||
{
|
||||
return expression is MemberExpression member
|
||||
&& member.Expression.Type == _shardingConfig.ShardingEntityType
|
||||
&& member.Member.Name == _shardingConfig.ShardingField;
|
||||
&& member.Expression.Type == _shardingConfig.EntityType
|
||||
&& member.Member.Name == _shardingConfig.ShardingTableField;
|
||||
}
|
||||
/// <summary>
|
||||
/// 方法是否包含shardingKey
|
||||
|
@ -52,8 +53,8 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
for (int i = 0; i < methodCallExpression.Arguments.Count; i++)
|
||||
{
|
||||
var isShardingKey = methodCallExpression.Arguments[i] is MemberExpression member
|
||||
&& member.Expression.Type == _shardingConfig.ShardingEntityType
|
||||
&& member.Member.Name == _shardingConfig.ShardingField;
|
||||
&& member.Expression.Type == _shardingConfig.EntityType
|
||||
&& member.Member.Name == _shardingConfig.ShardingTableField;
|
||||
if (isShardingKey) return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ShardingCore.Core.PhysicTables;
|
||||
using ShardingCore.Core.VirtualDatabase;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.PhysicDataSources;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualTables;
|
||||
|
@ -85,8 +86,13 @@ namespace ShardingCore
|
|||
var virtualTable = CreateVirtualTable(entityType, virtualRoute);
|
||||
|
||||
//获取ShardingEntity的实际表名
|
||||
#if !EFCORE2
|
||||
var tableName = context.Model.FindEntityType(virtualTable.EntityType).GetTableName();
|
||||
virtualTable.SetOriginalTableName(tableName);
|
||||
#endif
|
||||
#if EFCORE2
|
||||
var tableName = context.Model.FindEntityType(virtualTable.EntityType).Relational().TableName;
|
||||
#endif
|
||||
virtualTable.SetVirtualTableName(tableName);
|
||||
_virtualTableManager.AddVirtualTable(virtualTable);
|
||||
CreateDataTable(dataSourceName,virtualTable);
|
||||
}
|
||||
|
@ -174,7 +180,7 @@ namespace ShardingCore
|
|||
return (IVirtualTable)o;
|
||||
}
|
||||
|
||||
private bool NeedCreateTable(ShardingTableConfig config)
|
||||
private bool NeedCreateTable(ShardingEntityConfig config)
|
||||
{
|
||||
if (config.AutoCreateTable.HasValue)
|
||||
{
|
||||
|
|
|
@ -1,88 +1,72 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Core.Internal.Visitors.Querys;
|
||||
using ShardingCore.Core.VirtualRoutes;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
//using System;
|
||||
//using System.Collections.Concurrent;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Linq.Expressions;
|
||||
//using System.Reflection;
|
||||
//using ShardingCore.Core;
|
||||
//using ShardingCore.Core.Internal.Visitors;
|
||||
//using ShardingCore.Core.Internal.Visitors.Querys;
|
||||
//using ShardingCore.Core.VirtualRoutes;
|
||||
//using ShardingCore.Core.VirtualTables;
|
||||
|
||||
namespace ShardingCore.Utils
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Saturday, 19 December 2020 20:20:29
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingKeyUtil
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Type, ShardingTableConfig> _caches = new ConcurrentDictionary<Type, ShardingTableConfig>();
|
||||
//namespace ShardingCore.Utils
|
||||
//{
|
||||
///*
|
||||
//* @Author: xjm
|
||||
//* @Description:
|
||||
//* @Date: Saturday, 19 December 2020 20:20:29
|
||||
//* @Email: 326308290@qq.com
|
||||
//*/
|
||||
// public class ShardingKeyUtil
|
||||
// {
|
||||
// private static readonly ConcurrentDictionary<Type, ShardingTableConfig> _caches = new ConcurrentDictionary<Type, ShardingTableConfig>();
|
||||
|
||||
private ShardingKeyUtil()
|
||||
{
|
||||
}
|
||||
// private ShardingKeyUtil()
|
||||
// {
|
||||
// }
|
||||
|
||||
public static ShardingTableConfig Parse(Type entityType)
|
||||
{
|
||||
if (!typeof(IShardingTable).IsAssignableFrom(entityType))
|
||||
throw new NotSupportedException(entityType.ToString());
|
||||
if (_caches.TryGetValue(entityType, out var shardingEntityConfig))
|
||||
{
|
||||
return shardingEntityConfig;
|
||||
}
|
||||
// public static ShardingTableConfig Parse(Type entityType)
|
||||
// {
|
||||
// if (!typeof(IShardingTable).IsAssignableFrom(entityType))
|
||||
// throw new NotSupportedException(entityType.ToString());
|
||||
// if (_caches.TryGetValue(entityType, out var shardingEntityConfig))
|
||||
// {
|
||||
// return shardingEntityConfig;
|
||||
// }
|
||||
|
||||
PropertyInfo[] shardingProperties = entityType.GetProperties();
|
||||
foreach (var shardingProperty in shardingProperties)
|
||||
{
|
||||
var attribbutes = shardingProperty.GetCustomAttributes(true);
|
||||
if (attribbutes.FirstOrDefault(x => x.GetType() == typeof(ShardingTableKeyAttribute)) is ShardingTableKeyAttribute shardingKeyAttribute)
|
||||
{
|
||||
if (shardingEntityConfig != null)
|
||||
throw new ArgumentException($"{entityType} found more than one [ShardingKeyAttribute]");
|
||||
shardingEntityConfig = new ShardingTableConfig()
|
||||
{
|
||||
ShardingEntityType = entityType,
|
||||
ShardingField = shardingProperty.Name,
|
||||
AutoCreateTable = shardingKeyAttribute.AutoCreateTableOnStart==ShardingKeyAutoCreateTableEnum.UnKnown?(bool?)null:(shardingKeyAttribute.AutoCreateTableOnStart==ShardingKeyAutoCreateTableEnum.Create),
|
||||
TailPrefix = shardingKeyAttribute.TailPrefix
|
||||
};
|
||||
_caches.TryAdd(entityType, shardingEntityConfig);
|
||||
}
|
||||
}
|
||||
// PropertyInfo[] shardingProperties = entityType.GetProperties();
|
||||
// foreach (var shardingProperty in shardingProperties)
|
||||
// {
|
||||
// var attribbutes = shardingProperty.GetCustomAttributes(true);
|
||||
// if (attribbutes.FirstOrDefault(x => x.GetType() == typeof(ShardingTableKeyAttribute)) is ShardingTableKeyAttribute shardingKeyAttribute)
|
||||
// {
|
||||
// if (shardingEntityConfig != null)
|
||||
// throw new ArgumentException($"{entityType} found more than one [ShardingKeyAttribute]");
|
||||
// shardingEntityConfig = new ShardingTableConfig()
|
||||
// {
|
||||
// ShardingEntityType = entityType,
|
||||
// ShardingField = shardingProperty.Name,
|
||||
// AutoCreateTable = shardingKeyAttribute.AutoCreateTableOnStart==ShardingKeyAutoCreateTableEnum.UnKnown?(bool?)null:(shardingKeyAttribute.AutoCreateTableOnStart==ShardingKeyAutoCreateTableEnum.Create),
|
||||
// TailPrefix = shardingKeyAttribute.TailPrefix
|
||||
// };
|
||||
// _caches.TryAdd(entityType, shardingEntityConfig);
|
||||
// }
|
||||
// }
|
||||
|
||||
return shardingEntityConfig;
|
||||
}
|
||||
|
||||
public static Func<string, bool> GetRouteShardingTableFilter<TKey>(IQueryable queryable, ShardingTableConfig shardingConfig, Func<object, TKey> shardingKeyConvert, Func<TKey, ShardingOperatorEnum, Expression<Func<string, bool>>> keyToTailExpression)
|
||||
{
|
||||
QueryableRouteShardingTableDiscoverVisitor<TKey> visitor = new QueryableRouteShardingTableDiscoverVisitor<TKey>(shardingConfig, shardingKeyConvert, keyToTailExpression);
|
||||
|
||||
visitor.Visit(queryable.Expression);
|
||||
|
||||
return visitor.GetStringFilterTail();
|
||||
}
|
||||
// return shardingEntityConfig;
|
||||
// }
|
||||
|
||||
|
||||
public static ISet<Type> GetShardingEntitiesFilter(IQueryable queryable)
|
||||
{
|
||||
ShardingEntitiesVisitor visitor = new ShardingEntitiesVisitor();
|
||||
|
||||
visitor.Visit(queryable.Expression);
|
||||
// //public static ISet<Type> GetShardingEntitiesFilter(IQueryable queryable)
|
||||
// //{
|
||||
// // ShardingEntitiesVisitor visitor = new ShardingEntitiesVisitor();
|
||||
|
||||
return visitor.GetShardingEntities();
|
||||
}
|
||||
public static ISet<Type> GetQueryEntitiesFilter(IQueryable queryable)
|
||||
{
|
||||
QueryEntitiesVisitor visitor = new QueryEntitiesVisitor();
|
||||
// // visitor.Visit(queryable.Expression);
|
||||
|
||||
visitor.Visit(queryable.Expression);
|
||||
// // return visitor.GetShardingEntities();
|
||||
// //}
|
||||
|
||||
return visitor.GetQueryEntities();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
//}
|
|
@ -1,11 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.Internal;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Core.Internal.Visitors.Querys;
|
||||
using ShardingCore.Core.VirtualDatabase;
|
||||
using ShardingCore.Core.VirtualRoutes;
|
||||
using ShardingCore.Extensions;
|
||||
|
@ -28,13 +30,16 @@ namespace ShardingCore.Utils
|
|||
|
||||
public static ShardingEntityConfig Parse(Type entityType)
|
||||
{
|
||||
var isShardingTable = entityType.IsShardingTable();
|
||||
var isShardingDataSource = entityType.IsShardingDataSource();
|
||||
if (!isShardingTable && !isShardingDataSource)
|
||||
throw new InvalidOperationException(
|
||||
$"{entityType.FullName} is not impl {nameof(IShardingDataSource)} or {nameof(IShardingTable)}");
|
||||
if (_caches.TryGetValue(entityType, out var entityConfig))
|
||||
{
|
||||
return entityConfig;
|
||||
}
|
||||
|
||||
var isShardingTable = entityType.IsShardingTable();
|
||||
var isShardingDataSource = entityType.IsShardingDataSource();
|
||||
entityConfig = new ShardingEntityConfig()
|
||||
{
|
||||
EntityType = entityType,
|
||||
|
@ -43,17 +48,8 @@ namespace ShardingCore.Utils
|
|||
};
|
||||
|
||||
|
||||
//if (!isShardingDataSource && isShardingTable)
|
||||
// throw new NotSupportedException(entityType.FullName);
|
||||
|
||||
PropertyInfo[] shardingProperties = entityType.GetProperties();
|
||||
|
||||
//if (isShardingTable)
|
||||
//{
|
||||
// var shardingTables = shardingProperties.SelectMany(p => p.GetCustomAttributes(true).Where(o => o.GetType() == typeof(ShardingTableKeyAttribute))).ToList();
|
||||
// if (shardingTables.Count != 1)
|
||||
// throw new NotSupportedException($"{entityType} From IShardingTable should use single attribute [{nameof(ShardingTableKeyAttribute)}]");
|
||||
//}
|
||||
|
||||
|
||||
var shardingDataSourceCount = 0;
|
||||
var shardingTableCount = 0;
|
||||
|
@ -65,7 +61,7 @@ namespace ShardingCore.Utils
|
|||
if (attributes.FirstOrDefault(x => x.GetType() == typeof(ShardingDataSourceKeyAttribute)) is ShardingDataSourceKeyAttribute shardingDataSourceKey)
|
||||
{
|
||||
if (shardingDataSourceCount > 1)
|
||||
throw new NotSupportedException($"{entityType} From IShardingDataSource should use single attribute [{nameof(ShardingDataSourceKeyAttribute)}]");
|
||||
throw new NotSupportedException($"{entityType} impl {nameof(IShardingDataSource)} should use single attribute [{nameof(ShardingDataSourceKeyAttribute)}]");
|
||||
|
||||
entityConfig.ShardingDataSourceField = shardingProperty.Name;
|
||||
entityConfig.AutoCreateDataSource = shardingDataSourceKey.AutoCreateDataSourceOnStart == ShardingKeyAutoCreateDataSourceEnum.UnKnown ? (bool?)null : (shardingDataSourceKey.AutoCreateDataSourceOnStart == ShardingKeyAutoCreateDataSourceEnum.Create);
|
||||
|
@ -78,7 +74,7 @@ namespace ShardingCore.Utils
|
|||
if (attributes.FirstOrDefault(x => x.GetType() == typeof(ShardingTableKeyAttribute)) is ShardingTableKeyAttribute shardingKey)
|
||||
{
|
||||
if (shardingTableCount > 1)
|
||||
throw new NotSupportedException($"{entityType} From IShardingTable should use single attribute [{nameof(ShardingTableKeyAttribute)}]");
|
||||
throw new NotSupportedException($"{entityType} impl {nameof(IShardingTable)} should use single attribute [{nameof(ShardingTableKeyAttribute)}]");
|
||||
|
||||
entityConfig.ShardingTableField = shardingProperty.Name;
|
||||
entityConfig.AutoCreateTable = shardingKey.AutoCreateTableOnStart == ShardingKeyAutoCreateTableEnum.UnKnown ? (bool?) null : (shardingKey.AutoCreateTableOnStart == ShardingKeyAutoCreateTableEnum.Create);
|
||||
|
@ -93,7 +89,15 @@ namespace ShardingCore.Utils
|
|||
return entityConfig;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 分库路由过滤
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <param name="queryable"></param>
|
||||
/// <param name="shardingEntityBaseType"></param>
|
||||
/// <param name="shardingKeyConvert"></param>
|
||||
/// <param name="keyToTailExpression"></param>
|
||||
/// <returns></returns>
|
||||
public static Func<string, bool> GetRouteDataSourceFilter<TKey>(IQueryable queryable, ShardingEntityConfig shardingEntityBaseType, Func<object, TKey> shardingKeyConvert, Func<TKey, ShardingOperatorEnum, Expression<Func<string, bool>>> keyToTailExpression)
|
||||
{
|
||||
QueryableRouteShardingDataSourceDiscoverVisitor<TKey> visitor = new QueryableRouteShardingDataSourceDiscoverVisitor<TKey>(shardingEntityBaseType, shardingKeyConvert, keyToTailExpression);
|
||||
|
@ -102,6 +106,36 @@ namespace ShardingCore.Utils
|
|||
|
||||
return visitor.GetDataSourceFilter();
|
||||
}
|
||||
/// <summary>
|
||||
/// 分表路由过滤
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <param name="queryable"></param>
|
||||
/// <param name="shardingConfig"></param>
|
||||
/// <param name="shardingKeyConvert"></param>
|
||||
/// <param name="keyToTailExpression"></param>
|
||||
/// <returns></returns>
|
||||
public static Func<string, bool> GetRouteShardingTableFilter<TKey>(IQueryable queryable, ShardingEntityConfig shardingConfig, Func<object, TKey> shardingKeyConvert, Func<TKey, ShardingOperatorEnum, Expression<Func<string, bool>>> keyToTailExpression)
|
||||
{
|
||||
QueryableRouteShardingTableDiscoverVisitor<TKey> visitor = new QueryableRouteShardingTableDiscoverVisitor<TKey>(shardingConfig, shardingKeyConvert, keyToTailExpression);
|
||||
|
||||
visitor.Visit(queryable.Expression);
|
||||
|
||||
return visitor.GetStringFilterTail();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取本次查询的所有涉及到的对象
|
||||
/// </summary>
|
||||
/// <param name="queryable"></param>
|
||||
/// <returns></returns>
|
||||
public static ISet<Type> GetQueryEntitiesFilter(IQueryable queryable)
|
||||
{
|
||||
QueryEntitiesVisitor visitor = new QueryEntitiesVisitor();
|
||||
|
||||
visitor.Visit(queryable.Expression);
|
||||
|
||||
return visitor.GetQueryEntities();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<Version>$(EFCORE2)</Version>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<DefineConstants>TRACE;DEBUG;EFCORE2;</DefineConstants>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<AssemblyName>ShardingCore</AssemblyName>
|
||||
<RootNamespace>ShardingCore</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<DocumentationFile>bin\Release\ShardingCore.2x.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\src\ShardingCore\**\*.cs" />
|
||||
<Compile Remove="..\..\src\ShardingCore\obj\**" />
|
||||
<Compile Remove="..\..\src\ShardingCore\bin\**" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="..\..\src\ShardingCore\ShardingTableConfig.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.6" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,5 +1,5 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Test50.MySql.Domain.Maps;
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace ShardingCore.Test50
|
|||
{
|
||||
services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o =>
|
||||
o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]))
|
||||
.Begin(true)
|
||||
.Begin(true,true)
|
||||
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger))
|
||||
.AddShardingTransaction((connection, builder) =>builder.UseSqlServer(connection).UseLoggerFactory(efLogger))
|
||||
.AddDefaultDataSource("ds0",hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"])
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"SqlServer": {
|
||||
"ConnectionString": "Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Test50_2x.Domain.Maps;
|
||||
|
||||
namespace ShardingCore.Test50_2x
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/3/31 15:28:11
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class DefaultDbContext : DbContext, IShardingTableDbContext
|
||||
{
|
||||
public DefaultDbContext(DbContextOptions<DefaultDbContext> options) : base(options)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
modelBuilder.ApplyConfiguration(new SysUserModMap());
|
||||
modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
|
||||
}
|
||||
|
||||
public IRouteTail RouteTail { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using ShardingCore.Core;
|
||||
|
||||
namespace ShardingCore.Test50_2x.Domain.Entities
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Thursday, 14 January 2021 15:36:43
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserMod:IShardingTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户Id用于分表
|
||||
/// </summary>
|
||||
[ShardingTableKey(TailPrefix = "_")]
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
/// 用户名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// 用户姓名
|
||||
/// </summary>
|
||||
public int Age { get; set; }
|
||||
public int AgeGroup { get; set; }
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using ShardingCore.Core;
|
||||
|
||||
namespace ShardingCore.Test50_2x.Domain.Entities
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 01 February 2021 15:43:22
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserSalary:IShardingTable
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string UserId { get; set; }
|
||||
/// <summary>
|
||||
/// 每月的金额
|
||||
/// </summary>
|
||||
[ShardingTableKey]
|
||||
public int DateOfMonth { get; set; }
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public int Salary { get; set; }
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public long SalaryLong { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public decimal SalaryDecimal { get; set; }
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public double SalaryDouble { get; set; }
|
||||
/// <summary>
|
||||
/// 工资
|
||||
/// </summary>
|
||||
public float SalaryFloat { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using ShardingCore.Test50_2x.Domain.Entities;
|
||||
|
||||
namespace ShardingCore.Test50_2x.Domain.Maps
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Thursday, 14 January 2021 15:37:33
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserModMap:IEntityTypeConfiguration<SysUserMod>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<SysUserMod> builder)
|
||||
{
|
||||
builder.HasKey(o => o.Id);
|
||||
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
|
||||
builder.Property(o => o.Name).HasMaxLength(128);
|
||||
builder.ToTable(nameof(SysUserMod));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using ShardingCore.Test50_2x.Domain.Entities;
|
||||
|
||||
namespace ShardingCore.Test50_2x.Domain.Maps
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 01 February 2021 15:42:35
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserSalaryMap:IEntityTypeConfiguration<SysUserSalary>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<SysUserSalary> builder)
|
||||
{
|
||||
builder.HasKey(o => o.Id);
|
||||
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
|
||||
builder.Property(o => o.UserId).IsRequired().HasMaxLength(128);
|
||||
builder.ToTable(nameof(SysUserSalary));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.6" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Xunit.DependencyInjection" Version="7.1.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Configs\DbConfig.json">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src2x\ShardingCore.2x\ShardingCore.2x.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Sharding;
|
||||
using ShardingCore.Test50_2x.Domain.Maps;
|
||||
|
||||
namespace ShardingCore.Test50_2x
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/8/15 10:21:03
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingDefaultDbContext:AbstractShardingDbContext<DefaultDbContext>
|
||||
{
|
||||
public ShardingDefaultDbContext(DbContextOptions<ShardingDefaultDbContext> options) : base(options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
modelBuilder.ApplyConfiguration(new SysUserModMap());
|
||||
modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,417 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.QueryRouteManagers.Abstractions;
|
||||
using ShardingCore.Test50_2x.Domain.Entities;
|
||||
using Xunit;
|
||||
|
||||
namespace ShardingCore.Test50_2x
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Friday, 15 January 2021 17:22:10
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingTest
|
||||
{
|
||||
private readonly ShardingDefaultDbContext _virtualDbContext;
|
||||
private readonly IShardingRouteManager _shardingRouteManager;
|
||||
|
||||
public ShardingTest(ShardingDefaultDbContext virtualDbContext,IShardingRouteManager shardingRouteManager)
|
||||
{
|
||||
_virtualDbContext = virtualDbContext;
|
||||
_shardingRouteManager = shardingRouteManager;
|
||||
}
|
||||
|
||||
//[Fact]
|
||||
//public async Task Route_TEST()
|
||||
//{
|
||||
// var queryable1 = _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id=="339");
|
||||
// var routeResults1 = _routingRuleEngineFactory.Route(queryable1);
|
||||
// Assert.Equal(1,routeResults1.Count());
|
||||
// Assert.Equal(1,routeResults1.FirstOrDefault().ReplaceTables.Count());
|
||||
// Assert.Equal("0",routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().Tail);
|
||||
// Assert.Equal(nameof(SysUserMod),routeResults1.FirstOrDefault().ReplaceTables.FirstOrDefault().OriginalName);
|
||||
// var ids = new[] {"339", "124","142"};
|
||||
// var queryable2= _virtualDbContext.Set<SysUserMod>().Where(o=>ids.Contains(o.Id));
|
||||
// var routeResult2s = _routingRuleEngineFactory.Route(queryable2);
|
||||
// Assert.Equal(2,routeResult2s.Count());
|
||||
// Assert.Equal(1,routeResult2s.FirstOrDefault().ReplaceTables.Count());
|
||||
// Assert.Equal(2,routeResult2s.SelectMany(o=>o.ReplaceTables).Count());
|
||||
// Assert.Equal(true,routeResult2s.SelectMany(o=>o.ReplaceTables).All(o=>new[]{"0","1"}.Contains(o.Tail)));
|
||||
//}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_All_Route_Test()
|
||||
{
|
||||
using (_shardingRouteManager.CreateScope())
|
||||
{
|
||||
_shardingRouteManager.Current.Must.TryAdd(typeof(SysUserMod), new HashSet<string>() { "00" });
|
||||
|
||||
var mod00s = await _virtualDbContext.Set<SysUserMod>().ToListAsync();
|
||||
Assert.Equal(333, mod00s.Count);
|
||||
}
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().ToListAsync();
|
||||
Assert.Equal(1000, mods.Count);
|
||||
|
||||
var modOrders1 = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToListAsync();
|
||||
int ascAge = 1;
|
||||
foreach (var sysUserMod in modOrders1)
|
||||
{
|
||||
Assert.Equal(ascAge, sysUserMod.Age);
|
||||
ascAge++;
|
||||
}
|
||||
|
||||
|
||||
var modOrders2 = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ToListAsync();
|
||||
int descAge = 1000;
|
||||
foreach (var sysUserMod in modOrders2)
|
||||
{
|
||||
Assert.Equal(descAge, sysUserMod.Age);
|
||||
descAge--;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_All_Test()
|
||||
{
|
||||
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().ToListAsync();
|
||||
Assert.Equal(1000, mods.Count);
|
||||
|
||||
var modOrders1 = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToListAsync();
|
||||
int ascAge = 1;
|
||||
foreach (var sysUserMod in modOrders1)
|
||||
{
|
||||
Assert.Equal(ascAge, sysUserMod.Age);
|
||||
ascAge++;
|
||||
}
|
||||
|
||||
var modOrders2 = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ToListAsync();
|
||||
int descAge = 1000;
|
||||
foreach (var sysUserMod in modOrders2)
|
||||
{
|
||||
Assert.Equal(descAge, sysUserMod.Age);
|
||||
descAge--;
|
||||
}
|
||||
|
||||
var pageResult = await _virtualDbContext.Set<SysUserMod>().Skip(10).Take(10).OrderByDescending(o => o.Age).ToListAsync();
|
||||
Assert.Equal(10, pageResult.Count);
|
||||
int pageDescAge = 990;
|
||||
foreach (var sysUserMod in pageResult)
|
||||
{
|
||||
Assert.Equal(pageDescAge, sysUserMod.Age);
|
||||
pageDescAge--;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_Join_Test()
|
||||
{
|
||||
var list = await (from u in _virtualDbContext.Set<SysUserMod>()
|
||||
join salary in _virtualDbContext.Set<SysUserSalary>()
|
||||
on u.Id equals salary.UserId
|
||||
select new
|
||||
{
|
||||
u.Id,
|
||||
u.Age,
|
||||
Salary = salary.Salary,
|
||||
DateOfMonth = salary.DateOfMonth,
|
||||
Name = u.Name
|
||||
}).ToListAsync();
|
||||
var list2 = list.OrderBy(o=>o.Age).Select(o=>o.Age).Distinct().ToList();
|
||||
Assert.Equal(24000, list.Count());
|
||||
Assert.Equal(24, list.Count(o => o.Name == "name_200"));
|
||||
|
||||
|
||||
var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
|
||||
join salary in _virtualDbContext.Set<SysUserSalary>()
|
||||
on u.Id equals salary.UserId
|
||||
select new
|
||||
{
|
||||
Salary = salary.Salary,
|
||||
DateOfMonth = salary.DateOfMonth,
|
||||
Name = u.Name
|
||||
});
|
||||
var list1 = await queryable.ToListAsync();
|
||||
Assert.Equal(24, list1.Count());
|
||||
Assert.DoesNotContain(list1, o => o.Name != "name_300");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_OrderBy_Asc_Desc_Test()
|
||||
{
|
||||
var modascs = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToListAsync();
|
||||
Assert.Equal(1000, modascs.Count);
|
||||
var i = 1;
|
||||
foreach (var age in modascs)
|
||||
{
|
||||
Assert.Equal(i, age.Age);
|
||||
i++;
|
||||
}
|
||||
|
||||
var moddescs = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ToListAsync();
|
||||
Assert.Equal(1000, moddescs.Count);
|
||||
var j = 1000;
|
||||
foreach (var age in moddescs)
|
||||
{
|
||||
Assert.Equal(j, age.Age);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_Id_In_Test()
|
||||
{
|
||||
var ids = new[] {"1", "2", "3", "4"};
|
||||
var sysUserMods = await _virtualDbContext.Set<SysUserMod>().Where(o => ids.Contains(o.Id)).ToListAsync();
|
||||
foreach (var id in ids)
|
||||
{
|
||||
Assert.Contains(sysUserMods, o => o.Id == id);
|
||||
}
|
||||
|
||||
Assert.DoesNotContain(sysUserMods, o => o.Age > 4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_Id_Eq_Test()
|
||||
{
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "3").ToListAsync();
|
||||
Assert.Single(mods);
|
||||
Assert.Equal("3", mods[0].Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_Id_Not_Eq_Test()
|
||||
{
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").ToListAsync();
|
||||
Assert.Equal(999, mods.Count);
|
||||
Assert.DoesNotContain(mods, o => o.Id == "3");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_Id_Not_Eq_Skip_Test()
|
||||
{
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderBy(o => o.Age).Skip(2).ToListAsync();
|
||||
Assert.Equal(997, mods.Count);
|
||||
Assert.DoesNotContain(mods, o => o.Id == "3");
|
||||
Assert.Equal(4, mods[0].Age);
|
||||
Assert.Equal(5, mods[1].Age);
|
||||
|
||||
var modsDesc = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderByDescending(o => o.Age).Skip(13).ToListAsync();
|
||||
Assert.Equal(986, modsDesc.Count);
|
||||
Assert.DoesNotContain(mods, o => o.Id == "3");
|
||||
Assert.Equal(987, modsDesc[0].Age);
|
||||
Assert.Equal(986, modsDesc[1].Age);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_Name_Eq_Test()
|
||||
{
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_3").ToListAsync();
|
||||
Assert.Single(mods);
|
||||
Assert.Equal("3", mods[0].Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_Id_Eq_Not_In_Db_Test()
|
||||
{
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1001").ToListAsync();
|
||||
Assert.Empty(mods);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToList_Name_Eq_Not_In_Db_Test()
|
||||
{
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").ToListAsync();
|
||||
Assert.Empty(mods);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FirstOrDefault_Order_By_Id_Test()
|
||||
{
|
||||
var sysUserModAge = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).FirstOrDefaultAsync();
|
||||
Assert.True(sysUserModAge != null && sysUserModAge.Id == "1");
|
||||
var sysUserModAgeDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).FirstOrDefaultAsync();
|
||||
Assert.True(sysUserModAgeDesc != null && sysUserModAgeDesc.Id == "1000");
|
||||
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Id).FirstOrDefaultAsync();
|
||||
Assert.True(sysUserMod != null && sysUserMod.Id == "1");
|
||||
|
||||
var sysUserModDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Id).FirstOrDefaultAsync();
|
||||
Assert.True(sysUserModDesc != null && sysUserModDesc.Id == "999");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FirstOrDefault2()
|
||||
{
|
||||
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1").FirstOrDefaultAsync();
|
||||
Assert.NotNull(sysUserMod);
|
||||
Assert.True(sysUserMod.Id == "1");
|
||||
var user198 = await _virtualDbContext.Set<SysUserMod>().FirstOrDefaultAsync(o => o.Id == "198");
|
||||
Assert.True(user198.Id == "198");
|
||||
var userId198 = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o => o.Id).FirstOrDefaultAsync();
|
||||
Assert.Equal(userId198, "198");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FirstOrDefault3()
|
||||
{
|
||||
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_2").FirstOrDefaultAsync();
|
||||
Assert.NotNull(sysUserMod);
|
||||
Assert.Equal("2", sysUserMod.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FirstOrDefault4()
|
||||
{
|
||||
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "1").FirstOrDefaultAsync();
|
||||
Assert.NotNull(sysUserMod);
|
||||
Assert.True(sysUserMod.Id != "1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FirstOrDefault5()
|
||||
{
|
||||
var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").FirstOrDefaultAsync();
|
||||
Assert.Null(sysUserMod);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Count_Test()
|
||||
{
|
||||
var a = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1000").CountAsync();
|
||||
Assert.Equal(1, a);
|
||||
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").CountAsync();
|
||||
Assert.Equal(999, b);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sum_Test()
|
||||
{
|
||||
var a = await _virtualDbContext.Set<SysUserMod>().SumAsync(o => o.Age);
|
||||
var expected = 0;
|
||||
for (int i = 1; i <= 1000; i++)
|
||||
{
|
||||
expected += i;
|
||||
}
|
||||
|
||||
Assert.Equal(expected, a);
|
||||
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").SumAsync(o => o.Age);
|
||||
Assert.Equal(expected - 1000, b);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Max_Test()
|
||||
{
|
||||
var a = await _virtualDbContext.Set<SysUserMod>().MaxAsync(o => o.Age);
|
||||
Assert.Equal(1000, a);
|
||||
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").MaxAsync(o => o.Age);
|
||||
Assert.Equal(999, b);
|
||||
var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age < 500).MaxAsync(o => o.Age);
|
||||
Assert.Equal(499, c);
|
||||
var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age <= 500).MaxAsync(o => o.Age);
|
||||
Assert.Equal(500, e);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Max_Join_Test()
|
||||
{
|
||||
var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
|
||||
join salary in _virtualDbContext.Set<SysUserSalary>()
|
||||
on u.Id equals salary.UserId
|
||||
select new
|
||||
{
|
||||
Salary = salary.Salary,
|
||||
DateOfMonth = salary.DateOfMonth,
|
||||
Name = u.Name
|
||||
});
|
||||
var maxSalary = await queryable.MaxAsync(o => o.Salary);
|
||||
Assert.Equal(1390000, maxSalary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Min_Test()
|
||||
{
|
||||
var a = await _virtualDbContext.Set<SysUserMod>().MinAsync(o => o.Age);
|
||||
Assert.Equal(1, a);
|
||||
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").MinAsync(o => o.Age);
|
||||
Assert.Equal(2, b);
|
||||
var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).MinAsync(o => o.Age);
|
||||
Assert.Equal(501, c);
|
||||
var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).MinAsync(o => o.Age);
|
||||
Assert.Equal(500, e);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Any_Test()
|
||||
{
|
||||
var a = await _virtualDbContext.Set<SysUserMod>().AnyAsync(o => o.Age == 100);
|
||||
Assert.True(a);
|
||||
var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").AnyAsync(o => o.Age == 1);
|
||||
Assert.False(b);
|
||||
var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).AnyAsync(o => o.Age <= 500);
|
||||
Assert.False(c);
|
||||
var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).AnyAsync(o => o.Age <= 500);
|
||||
Assert.True(e);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Group_Test()
|
||||
{
|
||||
var ids = new[] {"200", "300"};
|
||||
var dateOfMonths = new[] {202111, 202110};
|
||||
var group = await (from u in _virtualDbContext.Set<SysUserSalary>()
|
||||
.Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
|
||||
group u by new
|
||||
{
|
||||
UId = u.UserId
|
||||
}
|
||||
into g
|
||||
select new
|
||||
{
|
||||
GroupUserId = g.Key.UId,
|
||||
Count = g.Count(),
|
||||
TotalSalary = g.Sum(o => o.Salary),
|
||||
AvgSalary = g.Average(o => o.Salary),
|
||||
AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
|
||||
MinSalary = g.Min(o => o.Salary),
|
||||
MaxSalary = g.Max(o => o.Salary)
|
||||
}).ToListAsync();
|
||||
Assert.Equal(2, group.Count);
|
||||
Assert.Equal(2, group[0].Count);
|
||||
Assert.Equal(2260000, group[0].TotalSalary);
|
||||
Assert.Equal(1130000, group[0].AvgSalary);
|
||||
Assert.Equal(11300, group[0].AvgSalaryDecimal);
|
||||
Assert.Equal(1120000, group[0].MinSalary);
|
||||
Assert.Equal(1140000, group[0].MaxSalary);
|
||||
}
|
||||
// [Fact]
|
||||
// public async Task Group_API_Test()
|
||||
// {
|
||||
// var ids = new[] {"200", "300"};
|
||||
// var dateOfMonths = new[] {202111, 202110};
|
||||
// var group = await _virtualDbContext.Set<SysUserSalary>()
|
||||
// .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
|
||||
// .ShardingGroupByAsync(g => new {UId = g.UserId}, g => new
|
||||
// {
|
||||
//
|
||||
// GroupUserId = g.Key.UId,
|
||||
// Count = g.Count(),
|
||||
// TotalSalary = g.Sum(o => o.Salary),
|
||||
// AvgSalary = g.Average(o => o.Salary),
|
||||
// AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
|
||||
// MinSalary = g.Min(o => o.Salary),
|
||||
// MaxSalary = g.Max(o => o.Salary)
|
||||
// });
|
||||
// Assert.Equal(2, group.Count);
|
||||
// Assert.Equal(2, group[0].Count);
|
||||
// Assert.Equal(2260000, group[0].TotalSalary);
|
||||
// Assert.Equal(1130000, group[0].AvgSalary);
|
||||
// Assert.Equal(11300, group[0].AvgSalaryDecimal);
|
||||
// Assert.Equal(1120000, group[0].MinSalary);
|
||||
// Assert.Equal(1140000, group[0].MaxSalary);
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using ShardingCore.Test50_2x.Domain.Entities;
|
||||
using ShardingCore.VirtualRoutes.Mods;
|
||||
|
||||
namespace ShardingCore.Test50_2x.Shardings
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Thursday, 14 January 2021 15:39:27
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute<SysUserMod>
|
||||
{
|
||||
protected override bool EnableHintRoute => true;
|
||||
public SysUserModVirtualTableRoute() : base(2,3)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using ShardingCore.Core.VirtualRoutes;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
|
||||
using ShardingCore.Test50_2x.Domain.Entities;
|
||||
|
||||
namespace ShardingCore.Test50_2x.Shardings
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 01 February 2021 15:54:55
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute<SysUserSalary,int>
|
||||
{
|
||||
protected override int ConvertToShardingKey(object shardingKey)
|
||||
{
|
||||
return Convert.ToInt32(shardingKey);
|
||||
}
|
||||
|
||||
public override string ShardingKeyToTail(object shardingKey)
|
||||
{
|
||||
var time = ConvertToShardingKey(shardingKey);
|
||||
return TimeFormatToTail(time);
|
||||
}
|
||||
|
||||
|
||||
public override List<string> GetAllTails()
|
||||
{
|
||||
var beginTime = new DateTime(2020, 1, 1);
|
||||
var endTime = new DateTime(2021, 12, 1);
|
||||
var list = new List<string>(24);
|
||||
var tempTime = beginTime;
|
||||
while (tempTime <= endTime)
|
||||
{
|
||||
list.Add($"{tempTime:yyyyMM}");
|
||||
tempTime = tempTime.AddMonths(1);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
protected string TimeFormatToTail(int time)
|
||||
{
|
||||
var dateOfMonth=DateTime.ParseExact($"{time}","yyyyMM",System.Globalization.CultureInfo.InvariantCulture,System.Globalization.DateTimeStyles.AdjustToUniversal);
|
||||
return $"{dateOfMonth:yyyyMM}";
|
||||
}
|
||||
|
||||
protected override Expression<Func<string, bool>> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator)
|
||||
{
|
||||
var t = TimeFormatToTail(shardingKey);
|
||||
switch (shardingOperator)
|
||||
{
|
||||
case ShardingOperatorEnum.GreaterThan:
|
||||
case ShardingOperatorEnum.GreaterThanOrEqual:
|
||||
return tail => String.Compare(tail, t, StringComparison.Ordinal) >= 0;
|
||||
case ShardingOperatorEnum.LessThan:
|
||||
return tail => String.Compare(tail, t, StringComparison.Ordinal) < 0;
|
||||
case ShardingOperatorEnum.LessThanOrEqual:
|
||||
return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0;
|
||||
case ShardingOperatorEnum.Equal: return tail => tail == t;
|
||||
default:
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine($"shardingOperator is not equal scan all table tail");
|
||||
#endif
|
||||
return tail => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ShardingCore.EFCores;
|
||||
using ShardingCore.Test50_2x.Domain.Entities;
|
||||
using ShardingCore.Test50_2x.Shardings;
|
||||
|
||||
namespace ShardingCore.Test50_2x
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Friday, 15 January 2021 15:37:46
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class Startup
|
||||
{
|
||||
public static readonly ILoggerFactory efLogger = LoggerFactory.Create(builder =>
|
||||
{
|
||||
builder.AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole();
|
||||
});
|
||||
// // 自定义 host 构建
|
||||
public void ConfigureHost(IHostBuilder hostBuilder)
|
||||
{
|
||||
hostBuilder
|
||||
.ConfigureAppConfiguration(builder =>
|
||||
{
|
||||
builder.AddJsonFile("Configs/DbConfig.json");
|
||||
//builder.AddJsonFile("Configs/MacDbConfig.json");
|
||||
});
|
||||
}
|
||||
|
||||
// 支持的形式:
|
||||
// ConfigureServices(IServiceCollection services)
|
||||
// ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
|
||||
// ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
|
||||
public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
|
||||
{
|
||||
//services.AddDbContext<DefaultDbContext>();
|
||||
|
||||
services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o =>
|
||||
o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]))
|
||||
.Begin(true, true)
|
||||
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger))
|
||||
.AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger))
|
||||
.AddDefaultDataSource("ds0", hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"])
|
||||
.AddShardingTable(op =>
|
||||
{
|
||||
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
||||
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
|
||||
}).End();
|
||||
}
|
||||
|
||||
// 可以添加要用到的方法参数,会自动从注册的服务中获取服务实例,类似于 asp.net core 里 Configure 方法
|
||||
public void Configure(IServiceProvider serviceProvider)
|
||||
{
|
||||
var shardingBootstrapper = serviceProvider.GetService<IShardingBootstrapper>();
|
||||
shardingBootstrapper.Start();
|
||||
// 有一些测试数据要初始化可以放在这里
|
||||
InitData(serviceProvider).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加种子数据
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"></param>
|
||||
/// <returns></returns>
|
||||
private async Task InitData(IServiceProvider serviceProvider)
|
||||
{
|
||||
using (var scope = serviceProvider.CreateScope())
|
||||
{
|
||||
var virtualDbContext = scope.ServiceProvider.GetService<ShardingDefaultDbContext>();
|
||||
if (!await virtualDbContext.Set<SysUserMod>().AnyAsync())
|
||||
{
|
||||
var ids = Enumerable.Range(1, 1000);
|
||||
var userMods = new List<SysUserMod>();
|
||||
var userSalaries = new List<SysUserSalary>();
|
||||
var beginTime = new DateTime(2020, 1, 1);
|
||||
var endTime = new DateTime(2021, 12, 1);
|
||||
foreach (var id in ids)
|
||||
{
|
||||
userMods.Add(new SysUserMod()
|
||||
{
|
||||
Id = id.ToString(),
|
||||
Age = id,
|
||||
Name = $"name_{id}",
|
||||
AgeGroup = Math.Abs(id % 10)
|
||||
});
|
||||
var tempTime = beginTime;
|
||||
var i = 0;
|
||||
while (tempTime <= endTime)
|
||||
{
|
||||
var dateOfMonth = $@"{tempTime:yyyyMM}";
|
||||
userSalaries.Add(new SysUserSalary()
|
||||
{
|
||||
Id = $@"{id}{dateOfMonth}",
|
||||
UserId = id.ToString(),
|
||||
DateOfMonth = int.Parse(dateOfMonth),
|
||||
Salary = 700000 + id * 100 * i,
|
||||
SalaryLong = 700000 + id * 100 * i,
|
||||
SalaryDecimal = (700000 + id * 100 * i) / 100m,
|
||||
SalaryDouble = (700000 + id * 100 * i) / 100d,
|
||||
SalaryFloat = (700000 + id * 100 * i) / 100f
|
||||
});
|
||||
tempTime = tempTime.AddMonths(1);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
await virtualDbContext.AddRangeAsync(userMods);
|
||||
await virtualDbContext.AddRangeAsync(userSalaries);
|
||||
|
||||
await virtualDbContext.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Test50_3x.Domain.Maps;
|
||||
|
||||
|
|
|
@ -25,6 +25,5 @@ namespace ShardingCore.Test50_3x
|
|||
modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
|
||||
}
|
||||
|
||||
public override Type ShardingDbContextType => this.GetType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,16 +41,17 @@ namespace ShardingCore.Test50_3x
|
|||
// ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
|
||||
public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
|
||||
{
|
||||
services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"])
|
||||
,op =>
|
||||
services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o =>
|
||||
o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]))
|
||||
.Begin(true, true)
|
||||
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger))
|
||||
.AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger))
|
||||
.AddDefaultDataSource("ds0", hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"])
|
||||
.AddShardingTable(op =>
|
||||
{
|
||||
op.EnsureCreatedWithOutShardingTable = true;
|
||||
op.CreateShardingTableOnStart = true;
|
||||
op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),
|
||||
(conStr,builder)=> builder.UseSqlServer(conStr).UseLoggerFactory(efLogger));
|
||||
op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
||||
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
|
||||
});
|
||||
}).End();
|
||||
}
|
||||
|
||||
// 可以添加要用到的方法参数,会自动从注册的服务中获取服务实例,类似于 asp.net core 里 Configure 方法
|
||||
|
|
Loading…
Reference in New Issue