代码完成编译

This commit is contained in:
xuejiaming 2022-07-03 17:25:24 +08:00
parent d18ba69dfc
commit 89a8e66a6f
5 changed files with 349 additions and 375 deletions

View File

@ -2,8 +2,6 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using ShardingCore; using ShardingCore;
using ShardingCore.Bootstrappers;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore6x.NoShardingDbContexts; using ShardingCore6x.NoShardingDbContexts;
using ShardingCore6x.ShardingDbContexts; using ShardingCore6x.ShardingDbContexts;
@ -16,7 +14,6 @@ namespace ShardingCore6x
{ {
private readonly DefaultDbContext _defaultDbContext; private readonly DefaultDbContext _defaultDbContext;
private readonly DefaultShardingDbContext _defaultShardingDbContext; private readonly DefaultShardingDbContext _defaultShardingDbContext;
private readonly IVirtualTableManager<DefaultShardingDbContext> _virtualTableManager;
public EFCoreCrud() public EFCoreCrud()
{ {
var services = new ServiceCollection(); var services = new ServiceCollection();
@ -30,13 +27,10 @@ namespace ShardingCore6x
services.AddShardingDbContext<DefaultShardingDbContext>(ServiceLifetime.Transient, ServiceLifetime.Transient) services.AddShardingDbContext<DefaultShardingDbContext>(ServiceLifetime.Transient, ServiceLifetime.Transient)
.AddEntityConfig(o => .AddEntityConfig(o =>
{ {
o.CreateShardingTableOnStart = true;
o.EnsureCreatedWithOutShardingTable = true;
o.AddShardingTableRoute<OrderVirtualTableRoute>(); o.AddShardingTableRoute<OrderVirtualTableRoute>();
}) })
.AddConfig(op => .AddConfig(op =>
{ {
op.ConfigId = "c1";
op.UseShardingQuery((conStr, builder) => op.UseShardingQuery((conStr, builder) =>
{ {
builder.UseSqlServer(conStr); builder.UseSqlServer(conStr);
@ -55,7 +49,8 @@ namespace ShardingCore6x
}).EnsureConfig(); }).EnsureConfig();
var buildServiceProvider = services.BuildServiceProvider(); var buildServiceProvider = services.BuildServiceProvider();
buildServiceProvider.GetRequiredService<IShardingBootstrapper>().Start(); buildServiceProvider.UseAutoShardingCreate();
buildServiceProvider.UseAutoTryCompensateTable();
ICollection<Order> orders = new LinkedList<Order>(); ICollection<Order> orders = new LinkedList<Order>();
using (var scope = buildServiceProvider.CreateScope()) using (var scope = buildServiceProvider.CreateScope())
@ -106,9 +101,8 @@ namespace ShardingCore6x
Console.WriteLine($"批量插入订单数据:{orders.Count},用时:{sp.ElapsedMilliseconds}"); Console.WriteLine($"批量插入订单数据:{orders.Count},用时:{sp.ElapsedMilliseconds}");
} }
} }
_defaultDbContext = ShardingContainer.GetService<DefaultDbContext>(); _defaultDbContext = buildServiceProvider.GetService<DefaultDbContext>();
_defaultShardingDbContext = ShardingContainer.GetService<DefaultShardingDbContext>(); _defaultShardingDbContext = buildServiceProvider.GetService<DefaultShardingDbContext>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<DefaultShardingDbContext>>();
} }

View File

@ -8,14 +8,10 @@ using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using ShardingCore; using ShardingCore;
using ShardingCore.Bootstrappers;
using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions; using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Core.VirtualTables;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.TableExists; using ShardingCore.TableExists;
using ShardingCore.TableExists.Abstractions;
using ShardingCoreBenchmark5x.NoShardingDbContexts; using ShardingCoreBenchmark5x.NoShardingDbContexts;
using ShardingCoreBenchmark5x.ShardingDbContexts; using ShardingCoreBenchmark5x.ShardingDbContexts;
@ -25,10 +21,6 @@ namespace ShardingCoreBenchmark5x
{ {
private readonly DefaultDbContext _defaultDbContext; private readonly DefaultDbContext _defaultDbContext;
private readonly DefaultShardingDbContext _defaultShardingDbContext; private readonly DefaultShardingDbContext _defaultShardingDbContext;
private readonly IVirtualTableManager<DefaultShardingDbContext> _virtualTableManager;
private readonly IVirtualTable<Order> _virtualTable;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IStreamMergeContextFactory<DefaultShardingDbContext> _streamMergeContextFactory;
public EFCoreCrud() public EFCoreCrud()
{ {
var services = new ServiceCollection(); var services = new ServiceCollection();
@ -38,13 +30,10 @@ namespace ShardingCoreBenchmark5x
services.AddShardingDbContext<DefaultShardingDbContext>(ServiceLifetime.Transient, ServiceLifetime.Transient) services.AddShardingDbContext<DefaultShardingDbContext>(ServiceLifetime.Transient, ServiceLifetime.Transient)
.AddEntityConfig(o => .AddEntityConfig(o =>
{ {
o.CreateShardingTableOnStart = true;
o.EnsureCreatedWithOutShardingTable = true;
o.AddShardingTableRoute<OrderVirtualTableRoute>(); o.AddShardingTableRoute<OrderVirtualTableRoute>();
}) })
.AddConfig(op => .AddConfig(op =>
{ {
op.ConfigId = "c1";
op.UseShardingQuery((conStr, builder) => op.UseShardingQuery((conStr, builder) =>
{ {
builder.UseSqlServer(conStr); builder.UseSqlServer(conStr);
@ -53,14 +42,14 @@ namespace ShardingCoreBenchmark5x
{ {
builder.UseSqlServer(connection); builder.UseSqlServer(connection);
}); });
op.ReplaceTableEnsureManager(sp => new SqlServerTableEnsureManager<DefaultShardingDbContext>());
op.AddDefaultDataSource("ds0", op.AddDefaultDataSource("ds0",
"Data Source=localhost;Initial Catalog=db2;Integrated Security=True;"); "Data Source=localhost;Initial Catalog=db2;Integrated Security=True;");
}).EnsureConfig(); }).ReplaceService<ITableEnsureManager,SqlServerTableEnsureManager>().EnsureConfig();
var buildServiceProvider = services.BuildServiceProvider(); var buildServiceProvider = services.BuildServiceProvider();
buildServiceProvider.GetRequiredService<IShardingBootstrapper>().Start(); buildServiceProvider.UseAutoShardingCreate();
buildServiceProvider.UseAutoTryCompensateTable();
ICollection<Order> orders = new LinkedList<Order>(); ICollection<Order> orders = new LinkedList<Order>();
using (var scope = buildServiceProvider.CreateScope()) using (var scope = buildServiceProvider.CreateScope())
@ -111,17 +100,8 @@ namespace ShardingCoreBenchmark5x
Console.WriteLine($"批量插入订单数据:{orders.Count},用时:{sp.ElapsedMilliseconds}"); Console.WriteLine($"批量插入订单数据:{orders.Count},用时:{sp.ElapsedMilliseconds}");
} }
} }
_defaultDbContext = ShardingContainer.GetService<DefaultDbContext>(); _defaultDbContext = buildServiceProvider.GetService<DefaultDbContext>();
_defaultShardingDbContext = ShardingContainer.GetService<DefaultShardingDbContext>(); _defaultShardingDbContext = buildServiceProvider.GetService<DefaultShardingDbContext>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<DefaultShardingDbContext>>();
_virtualTable = _virtualTableManager.GetVirtualTable<Order>();
_routeTailFactory= ShardingContainer.GetService<IRouteTailFactory>();
_streamMergeContextFactory =
ShardingContainer.GetService<IStreamMergeContextFactory<DefaultShardingDbContext>>();
var queryable1 = _defaultShardingDbContext.Set<Order>().Where(o => o.Id == "0");
_virtualTable.RouteTo(new ShardingTableRouteConfig(queryable: queryable1));
var queryable = _defaultShardingDbContext.Set<Order>().Where(o => o.Id == "1000");
_virtualTable.RouteTo(new ShardingTableRouteConfig(queryable: queryable));
} }

View File

@ -1,153 +1,153 @@
using System.Collections.Concurrent; // using System.Collections.Concurrent;
using System.Linq.Expressions; // using System.Linq.Expressions;
using MySqlConnector; // using MySqlConnector;
using Newtonsoft.Json; // using Newtonsoft.Json;
using ShardingCore.Core.EntityMetadatas; // using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables; // using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; // using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualTables; // using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes; // using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; // using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Exceptions; // using ShardingCore.Exceptions;
using ShardingCore.Extensions; // using ShardingCore.Extensions;
using ShardingCore.TableCreator; // using ShardingCore.TableCreator;
//
namespace Sample.AutoCreateIfPresent // namespace Sample.AutoCreateIfPresent
{ // {
public class AreaDeviceRoute : AbstractShardingOperatorVirtualTableRoute<AreaDevice, string> // public class AreaDeviceRoute : AbstractShardingOperatorVirtualTableRoute<AreaDevice, string>
{ // {
private const string Tables = "Tables"; // private const string Tables = "Tables";
private const string TABLE_SCHEMA = "TABLE_SCHEMA"; // private const string TABLE_SCHEMA = "TABLE_SCHEMA";
private const string TABLE_NAME = "TABLE_NAME"; // private const string TABLE_NAME = "TABLE_NAME";
//
private const string CurrentTableName = nameof(AreaDevice); // private const string CurrentTableName = nameof(AreaDevice);
private readonly IVirtualDataSourceManager<DefaultDbContext> _virtualDataSourceManager; // private readonly IVirtualDataSourceManager<DefaultDbContext> _virtualDataSourceManager;
private readonly IVirtualTableManager<DefaultDbContext> _virtualTableManager; // private readonly IVirtualTableManager<DefaultDbContext> _virtualTableManager;
private readonly IShardingTableCreator<DefaultDbContext> _shardingTableCreator; // private readonly IShardingTableCreator<DefaultDbContext> _shardingTableCreator;
private readonly ConcurrentDictionary<string, object?> _tails = new ConcurrentDictionary<string, object?>(); // private readonly ConcurrentDictionary<string, object?> _tails = new ConcurrentDictionary<string, object?>();
private readonly object _lock = new object(); // private readonly object _lock = new object();
//
public AreaDeviceRoute(IVirtualDataSourceManager<DefaultDbContext> virtualDataSourceManager, IVirtualTableManager<DefaultDbContext> virtualTableManager, IShardingTableCreator<DefaultDbContext> shardingTableCreator) // public AreaDeviceRoute(IVirtualDataSourceManager<DefaultDbContext> virtualDataSourceManager, IVirtualTableManager<DefaultDbContext> virtualTableManager, IShardingTableCreator<DefaultDbContext> shardingTableCreator)
{ // {
_virtualDataSourceManager = virtualDataSourceManager; // _virtualDataSourceManager = virtualDataSourceManager;
_virtualTableManager = virtualTableManager; // _virtualTableManager = virtualTableManager;
_shardingTableCreator = shardingTableCreator; // _shardingTableCreator = shardingTableCreator;
} // }
//
//
public override string ShardingKeyToTail(object shardingKey) // public override string ShardingKeyToTail(object shardingKey)
{ // {
return $"{shardingKey}"; // return $"{shardingKey}";
} // }
/// <summary> // /// <summary>
/// 如果你是非mysql数据库请自行实现这个方法返回当前类在数据库已经存在的后缀 // /// 如果你是非mysql数据库请自行实现这个方法返回当前类在数据库已经存在的后缀
/// 仅启动时调用 // /// 仅启动时调用
/// </summary> // /// </summary>
/// <returns></returns> // /// <returns></returns>
public override List<string> GetAllTails() // public override List<string> GetAllTails()
{ // {
//启动寻找有哪些表后缀 // //启动寻找有哪些表后缀
using (var connection = new MySqlConnection(_virtualDataSourceManager.GetCurrentVirtualDataSource().DefaultConnectionString)) // using (var connection = new MySqlConnection(_virtualDataSourceManager.GetCurrentVirtualDataSource().DefaultConnectionString))
{ // {
connection.Open(); // connection.Open();
var database = connection.Database; // var database = connection.Database;
//
using (var dataTable = connection.GetSchema(Tables)) // using (var dataTable = connection.GetSchema(Tables))
{ // {
for (int i = 0; i < dataTable.Rows.Count; i++) // for (int i = 0; i < dataTable.Rows.Count; i++)
{ // {
var schema = dataTable.Rows[i][TABLE_SCHEMA]; // var schema = dataTable.Rows[i][TABLE_SCHEMA];
if (database.Equals($"{schema}", StringComparison.OrdinalIgnoreCase)) // if (database.Equals($"{schema}", StringComparison.OrdinalIgnoreCase))
{ // {
var tableName = dataTable.Rows[i][TABLE_NAME]?.ToString() ?? string.Empty; // var tableName = dataTable.Rows[i][TABLE_NAME]?.ToString() ?? string.Empty;
if (tableName.StartsWith(CurrentTableName,StringComparison.OrdinalIgnoreCase)) // if (tableName.StartsWith(CurrentTableName,StringComparison.OrdinalIgnoreCase))
{ // {
//如果没有下划线那么需要CurrentTableName.Length有下划线就要CurrentTableName.Length+1 // //如果没有下划线那么需要CurrentTableName.Length有下划线就要CurrentTableName.Length+1
_tails.TryAdd(tableName.Substring(CurrentTableName.Length+1), null); // _tails.TryAdd(tableName.Substring(CurrentTableName.Length+1), null);
} // }
} // }
} // }
} // }
} // }
return _tails.Keys.ToList(); // return _tails.Keys.ToList();
} // }
//
public override void Configure(EntityMetadataTableBuilder<AreaDevice> builder) // public override void Configure(EntityMetadataTableBuilder<AreaDevice> builder)
{ // {
builder.ShardingProperty(o => o.Area); // builder.ShardingProperty(o => o.Area);
} // }
//
public override Func<string, bool> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator) // public override Func<string, bool> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator)
{ // {
var t = ShardingKeyToTail(shardingKey); // var t = ShardingKeyToTail(shardingKey);
switch (shardingOperator) // switch (shardingOperator)
{ // {
case ShardingOperatorEnum.Equal: return tail => tail == t; // case ShardingOperatorEnum.Equal: return tail => tail == t;
default: // default:
{ // {
#if DEBUG // #if DEBUG
Console.WriteLine($"shardingOperator is not equal scan all table tail"); // Console.WriteLine($"shardingOperator is not equal scan all table tail");
#endif // #endif
return tail => true; // return tail => true;
} // }
} // }
} // }
//
public override IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey) // public override IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey)
{ // {
var shardingKeyToTail = ShardingKeyToTail(shardingKey); // var shardingKeyToTail = ShardingKeyToTail(shardingKey);
//
if (!_tails.TryGetValue(shardingKeyToTail, out var _)) // if (!_tails.TryGetValue(shardingKeyToTail, out var _))
{ // {
lock (_lock) // lock (_lock)
{ // {
if (!_tails.TryGetValue(shardingKeyToTail, out var _)) // if (!_tails.TryGetValue(shardingKeyToTail, out var _))
{ // {
var virtualTable = _virtualTableManager.GetVirtualTable(typeof(AreaDevice)); // var virtualTable = _virtualTableManager.GetVirtualTable(typeof(AreaDevice));
_virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, shardingKeyToTail)); // _virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, shardingKeyToTail));
try // try
{ // {
_shardingTableCreator.CreateTable<AreaDevice>(_virtualDataSourceManager.GetCurrentVirtualDataSource().DefaultDataSourceName, shardingKeyToTail); // _shardingTableCreator.CreateTable<AreaDevice>(_virtualDataSourceManager.GetCurrentVirtualDataSource().DefaultDataSourceName, shardingKeyToTail);
} // }
catch (Exception ex) // catch (Exception ex)
{ // {
Console.WriteLine("尝试添加表失败" + ex); // Console.WriteLine("尝试添加表失败" + ex);
} // }
//
_tails.TryAdd(shardingKeyToTail, null); // _tails.TryAdd(shardingKeyToTail, null);
} // }
} // }
} // }
//
var needRefresh = allPhysicTables.Count != _tails.Count; // var needRefresh = allPhysicTables.Count != _tails.Count;
if (needRefresh) // if (needRefresh)
{ // {
var virtualTable = _virtualTableManager.GetVirtualTable(typeof(AreaDevice)); // var virtualTable = _virtualTableManager.GetVirtualTable(typeof(AreaDevice));
//修复可能导致迭代器遍历时添加的bug // //修复可能导致迭代器遍历时添加的bug
var keys = _tails.Keys.ToList(); // var keys = _tails.Keys.ToList();
foreach (var tail in keys) // foreach (var tail in keys)
{ // {
var hashSet = allPhysicTables.Select(o => o.Tail).ToHashSet(); // var hashSet = allPhysicTables.Select(o => o.Tail).ToHashSet();
if (!hashSet.Contains(tail)) // if (!hashSet.Contains(tail))
{ // {
var tables = virtualTable.GetAllPhysicTables(); // var tables = virtualTable.GetAllPhysicTables();
var physicTable = tables.FirstOrDefault(o => o.Tail == tail); // var physicTable = tables.FirstOrDefault(o => o.Tail == tail);
if (physicTable != null) // if (physicTable != null)
{ // {
allPhysicTables.Add(physicTable); // allPhysicTables.Add(physicTable);
} // }
} // }
} // }
} // }
var physicTables = allPhysicTables.Where(o => o.Tail == shardingKeyToTail).ToList(); // var physicTables = allPhysicTables.Where(o => o.Tail == shardingKeyToTail).ToList();
if (physicTables.IsEmpty()) // if (physicTables.IsEmpty())
{ // {
throw new ShardingCoreException($"sharding key route not match {EntityMetadata.EntityType} -> [{EntityMetadata.ShardingTableProperty.Name}] ->【{shardingKey}】 all tails ->[{string.Join(",", allPhysicTables.Select(o => o.FullName))}]"); // throw new ShardingCoreException($"sharding key route not match {EntityMetadata.EntityType} -> [{EntityMetadata.ShardingTableProperty.Name}] ->【{shardingKey}】 all tails ->[{string.Join(",", allPhysicTables.Select(o => o.FullName))}]");
} // }
//
if (physicTables.Count > 1) // if (physicTables.Count > 1)
throw new ShardingCoreException($"more than one route match table:{string.Join(",", physicTables.Select(o => $"[{o.FullName}]"))}"); // throw new ShardingCoreException($"more than one route match table:{string.Join(",", physicTables.Select(o => $"[{o.FullName}]"))}");
return physicTables[0]; // return physicTables[0];
} // }
} // }
} // }

View File

@ -1,184 +1,184 @@
using System; // using System;
using System.Collections.Concurrent; // using System.Collections.Concurrent;
using System.Linq.Expressions; // using System.Linq.Expressions;
using MySqlConnector; // using MySqlConnector;
using ShardingCore; // using ShardingCore;
using ShardingCore.Core.EntityMetadatas; // using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.PhysicTables; // using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.ShardingConfigurations; // using ShardingCore.Core.ShardingConfigurations;
using ShardingCore.Core.ShardingConfigurations.Abstractions; // using ShardingCore.Core.ShardingConfigurations.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions; // using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
using ShardingCore.Core.VirtualDatabase.VirtualTables; // using ShardingCore.Core.VirtualDatabase.VirtualTables;
using ShardingCore.Core.VirtualRoutes; // using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; // using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions;
using ShardingCore.Exceptions; // using ShardingCore.Exceptions;
using ShardingCore.Extensions; // using ShardingCore.Extensions;
using ShardingCore.TableCreator; // using ShardingCore.TableCreator;
using ShardingCore.TableExists; // using ShardingCore.TableExists;
//
/* // /*
* @Author: xjm // * @Author: xjm
* @Description: // * @Description:
* @Date: DATE // * @Date: DATE
* @Email: 326308290@qq.com // * @Email: 326308290@qq.com
*/ // */
namespace Sample.AutoCreateIfPresent // namespace Sample.AutoCreateIfPresent
{ // {
public class OrderByHourRoute : AbstractShardingOperatorVirtualTableRoute<OrderByHour, DateTime> // public class OrderByHourRoute : AbstractShardingOperatorVirtualTableRoute<OrderByHour, DateTime>
{ // {
private const string Tables = "Tables"; // private const string Tables = "Tables";
private const string TABLE_SCHEMA = "TABLE_SCHEMA"; // private const string TABLE_SCHEMA = "TABLE_SCHEMA";
private const string TABLE_NAME = "TABLE_NAME"; // private const string TABLE_NAME = "TABLE_NAME";
//
private const string CurrentTableName = nameof(OrderByHour); // private const string CurrentTableName = nameof(OrderByHour);
private readonly IVirtualDataSourceManager<DefaultDbContext> _virtualDataSourceManager; // private readonly IVirtualDataSourceManager<DefaultDbContext> _virtualDataSourceManager;
private readonly IVirtualTableManager<DefaultDbContext> _virtualTableManager; // private readonly IVirtualTableManager<DefaultDbContext> _virtualTableManager;
private readonly IShardingTableCreator<DefaultDbContext> _shardingTableCreator; // private readonly IShardingTableCreator<DefaultDbContext> _shardingTableCreator;
private readonly ConcurrentDictionary<string, object?> _tails = new ConcurrentDictionary<string, object?>(); // private readonly ConcurrentDictionary<string, object?> _tails = new ConcurrentDictionary<string, object?>();
private readonly object _lock = new object(); // private readonly object _lock = new object();
//
public OrderByHourRoute(IVirtualDataSourceManager<DefaultDbContext> virtualDataSourceManager,IVirtualTableManager<DefaultDbContext> virtualTableManager, IShardingTableCreator<DefaultDbContext> shardingTableCreator) // public OrderByHourRoute(IVirtualDataSourceManager<DefaultDbContext> virtualDataSourceManager,IVirtualTableManager<DefaultDbContext> virtualTableManager, IShardingTableCreator<DefaultDbContext> shardingTableCreator)
{ // {
_virtualDataSourceManager = virtualDataSourceManager; // _virtualDataSourceManager = virtualDataSourceManager;
_virtualTableManager = virtualTableManager; // _virtualTableManager = virtualTableManager;
_shardingTableCreator = shardingTableCreator; // _shardingTableCreator = shardingTableCreator;
} // }
//
public override string ShardingKeyToTail(object shardingKey) // public override string ShardingKeyToTail(object shardingKey)
{ // {
var dateTime = (DateTime)shardingKey; // var dateTime = (DateTime)shardingKey;
return ShardingKeyFormat(dateTime); // return ShardingKeyFormat(dateTime);
} // }
private string ShardingKeyFormat(DateTime dateTime) // private string ShardingKeyFormat(DateTime dateTime)
{ // {
var tail = $"{dateTime:yyyyMMddHH}"; // var tail = $"{dateTime:yyyyMMddHH}";
//
return tail; // return tail;
} // }
//
/// <summary> // /// <summary>
/// 如果你是非mysql数据库请自行实现这个方法返回当前类在数据库已经存在的后缀 // /// 如果你是非mysql数据库请自行实现这个方法返回当前类在数据库已经存在的后缀
/// 仅启动时调用 // /// 仅启动时调用
/// </summary> // /// </summary>
/// <returns></returns> // /// <returns></returns>
public override List<string> GetTails() // public override List<string> GetTails()
{ // {
//启动寻找有哪些表后缀 // //启动寻找有哪些表后缀
using (var connection = new MySqlConnection(_virtualDataSourceManager.GetCurrentVirtualDataSource().DefaultConnectionString)) // using (var connection = new MySqlConnection(_virtualDataSourceManager.GetCurrentVirtualDataSource().DefaultConnectionString))
{ // {
connection.Open(); // connection.Open();
var database = connection.Database; // var database = connection.Database;
//
using (var dataTable = connection.GetSchema(Tables)) // using (var dataTable = connection.GetSchema(Tables))
{ // {
for (int i = 0; i < dataTable.Rows.Count; i++) // for (int i = 0; i < dataTable.Rows.Count; i++)
{ // {
var schema = dataTable.Rows[i][TABLE_SCHEMA]; // var schema = dataTable.Rows[i][TABLE_SCHEMA];
if (database.Equals($"{schema}", StringComparison.OrdinalIgnoreCase)) // if (database.Equals($"{schema}", StringComparison.OrdinalIgnoreCase))
{ // {
var tableName = dataTable.Rows[i][TABLE_NAME]?.ToString()??string.Empty; // var tableName = dataTable.Rows[i][TABLE_NAME]?.ToString()??string.Empty;
if (tableName.StartsWith(CurrentTableName, StringComparison.OrdinalIgnoreCase)) // if (tableName.StartsWith(CurrentTableName, StringComparison.OrdinalIgnoreCase))
{ // {
//如果没有下划线那么需要CurrentTableName.Length有下划线就要CurrentTableName.Length+1 // //如果没有下划线那么需要CurrentTableName.Length有下划线就要CurrentTableName.Length+1
_tails.TryAdd(tableName.Substring(CurrentTableName.Length+1),null); // _tails.TryAdd(tableName.Substring(CurrentTableName.Length+1),null);
} // }
} // }
} // }
} // }
} // }
return _tails.Keys.ToList(); // return _tails.Keys.ToList();
} // }
//
public override void Configure(EntityMetadataTableBuilder<OrderByHour> builder) // public override void Configure(EntityMetadataTableBuilder<OrderByHour> builder)
{ // {
builder.ShardingProperty(o => o.CreateTime); // builder.ShardingProperty(o => o.CreateTime);
} // }
//
public override Func<string, bool> GetRouteToFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) // public override Func<string, bool> GetRouteToFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator)
{ // {
var t = ShardingKeyFormat(shardingKey); // var t = ShardingKeyFormat(shardingKey);
switch (shardingOperator) // switch (shardingOperator)
{ // {
case ShardingOperatorEnum.GreaterThan: // case ShardingOperatorEnum.GreaterThan:
case ShardingOperatorEnum.GreaterThanOrEqual: // case ShardingOperatorEnum.GreaterThanOrEqual:
return tail => String.Compare(tail, t, StringComparison.Ordinal) >= 0; // return tail => String.Compare(tail, t, StringComparison.Ordinal) >= 0;
case ShardingOperatorEnum.LessThan: // case ShardingOperatorEnum.LessThan:
{ // {
var currentHourBeginTime = new DateTime(shardingKey.Year,shardingKey.Month,shardingKey.Day,shardingKey.Hour,0,0); // var currentHourBeginTime = new DateTime(shardingKey.Year,shardingKey.Month,shardingKey.Day,shardingKey.Hour,0,0);
//处于临界值 o=>o.time < [2021-01-01 00:00:00] 尾巴20210101不应该被返回 // //处于临界值 o=>o.time < [2021-01-01 00:00:00] 尾巴20210101不应该被返回
if (currentHourBeginTime == shardingKey) // if (currentHourBeginTime == shardingKey)
return tail => String.Compare(tail, t, StringComparison.Ordinal) < 0; // return tail => String.Compare(tail, t, StringComparison.Ordinal) < 0;
return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0; // return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0;
} // }
case ShardingOperatorEnum.LessThanOrEqual: // case ShardingOperatorEnum.LessThanOrEqual:
return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0; // return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0;
case ShardingOperatorEnum.Equal: return tail => tail == t; // case ShardingOperatorEnum.Equal: return tail => tail == t;
default: // default:
{ // {
#if DEBUG // #if DEBUG
Console.WriteLine($"shardingOperator is not equal scan all table tail"); // Console.WriteLine($"shardingOperator is not equal scan all table tail");
#endif // #endif
return tail => true; // return tail => true;
} // }
} // }
} // }
//
public override IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey) // public override IPhysicTable RouteWithValue(List<IPhysicTable> allPhysicTables, object shardingKey)
{ // {
var shardingKeyToTail = ShardingKeyToTail(shardingKey); // var shardingKeyToTail = ShardingKeyToTail(shardingKey);
//
if (!_tails.TryGetValue(shardingKeyToTail,out var _)) // if (!_tails.TryGetValue(shardingKeyToTail,out var _))
{ // {
lock (_lock) // lock (_lock)
{ // {
if (!_tails.TryGetValue(shardingKeyToTail,out var _)) // if (!_tails.TryGetValue(shardingKeyToTail,out var _))
{ // {
var virtualTable = _virtualTableManager.GetVirtualTable(typeof(OrderByHour)); // var virtualTable = _virtualTableManager.GetVirtualTable(typeof(OrderByHour));
//必须先执行AddPhysicTable在进行CreateTable // //必须先执行AddPhysicTable在进行CreateTable
_virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, shardingKeyToTail)); // _virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, shardingKeyToTail));
try // try
{ // {
_shardingTableCreator.CreateTable<OrderByHour>(_virtualDataSourceManager.GetCurrentVirtualDataSource().DefaultDataSourceName, shardingKeyToTail); // _shardingTableCreator.CreateTable<OrderByHour>(_virtualDataSourceManager.GetCurrentVirtualDataSource().DefaultDataSourceName, shardingKeyToTail);
} // }
catch (Exception ex) // catch (Exception ex)
{ // {
Console.WriteLine("尝试添加表失败" + ex); // Console.WriteLine("尝试添加表失败" + ex);
} // }
//
_tails.TryAdd(shardingKeyToTail,null); // _tails.TryAdd(shardingKeyToTail,null);
} // }
} // }
} // }
//
var needRefresh = allPhysicTables.Count != _tails.Count; // var needRefresh = allPhysicTables.Count != _tails.Count;
if (needRefresh) // if (needRefresh)
{ // {
var virtualTable = _virtualTableManager.GetVirtualTable(typeof(OrderByHour)); // var virtualTable = _virtualTableManager.GetVirtualTable(typeof(OrderByHour));
//修复可能导致迭代器遍历时添加的bug // //修复可能导致迭代器遍历时添加的bug
var keys = _tails.Keys.ToList(); // var keys = _tails.Keys.ToList();
foreach (var tail in keys) // foreach (var tail in keys)
{ // {
var hashSet = allPhysicTables.Select(o=>o.Tail).ToHashSet(); // var hashSet = allPhysicTables.Select(o=>o.Tail).ToHashSet();
if (!hashSet.Contains(tail)) // if (!hashSet.Contains(tail))
{ // {
var tables = virtualTable.GetAllPhysicTables(); // var tables = virtualTable.GetAllPhysicTables();
var physicTable = tables.FirstOrDefault(o=>o.Tail==tail); // var physicTable = tables.FirstOrDefault(o=>o.Tail==tail);
if (physicTable!= null) // if (physicTable!= null)
{ // {
allPhysicTables.Add(physicTable); // allPhysicTables.Add(physicTable);
} // }
} // }
} // }
} // }
var physicTables = allPhysicTables.Where(o => o.Tail== shardingKeyToTail).ToList(); // var physicTables = allPhysicTables.Where(o => o.Tail== shardingKeyToTail).ToList();
if (physicTables.IsEmpty()) // if (physicTables.IsEmpty())
{ // {
throw new ShardingCoreException($"sharding key route not match {EntityMetadata.EntityType} -> [{EntityMetadata.ShardingTableProperty.Name}] ->【{shardingKey}】 all tails ->[{string.Join(",", allPhysicTables.Select(o=>o.FullName))}]"); // throw new ShardingCoreException($"sharding key route not match {EntityMetadata.EntityType} -> [{EntityMetadata.ShardingTableProperty.Name}] ->【{shardingKey}】 all tails ->[{string.Join(",", allPhysicTables.Select(o=>o.FullName))}]");
} // }
//
if (physicTables.Count > 1) // if (physicTables.Count > 1)
throw new ShardingCoreException($"more than one route match table:{string.Join(",", physicTables.Select(o => $"[{o.FullName}]"))}"); // throw new ShardingCoreException($"more than one route match table:{string.Join(",", physicTables.Select(o => $"[{o.FullName}]"))}");
return physicTables[0]; // return physicTables[0];
} // }
} // }
} // }

View File

@ -22,8 +22,8 @@ builder.Services.AddShardingDbContext<DefaultDbContext>()
.AddEntityConfig(o => .AddEntityConfig(o =>
{ {
o.ThrowIfQueryRouteNotMatch = false; o.ThrowIfQueryRouteNotMatch = false;
o.AddShardingTableRoute<OrderByHourRoute>(); // o.AddShardingTableRoute<OrderByHourRoute>();
o.AddShardingTableRoute<AreaDeviceRoute>(); // o.AddShardingTableRoute<AreaDeviceRoute>();
}) })
.AddConfig(o => .AddConfig(o =>
{ {