using System.Collections.Concurrent; using MySqlConnector; using ShardingCore.Core.EntityMetadatas; using ShardingCore.Core.VirtualDatabase.VirtualDataSources; using ShardingCore.Core.VirtualRoutes; using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions; using ShardingCore.TableCreator; namespace Sample.AutoCreateIfPresent { public class AreaDeviceRoute : AbstractShardingOperatorVirtualTableRoute { private readonly IVirtualDataSource _virtualDataSource; private readonly IShardingTableCreator _tableCreator; private const string Tables = "Tables"; private const string TABLE_SCHEMA = "TABLE_SCHEMA"; private const string TABLE_NAME = "TABLE_NAME"; private const string CurrentTableName = nameof(AreaDevice); private readonly ConcurrentDictionary _tails = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private readonly object _lock = new object(); private readonly object _initLock = new object(); private bool _inited = false; public AreaDeviceRoute(IVirtualDataSource virtualDataSource, IShardingTableCreator tableCreator) { _virtualDataSource = virtualDataSource; _tableCreator = tableCreator; } private void InitTails() { using (var connection = new MySqlConnection(_virtualDataSource.DefaultConnectionString)) { connection.Open(); var database = connection.Database; using (var dataTable = connection.GetSchema(Tables)) { for (int i = 0; i < dataTable.Rows.Count; i++) { var schema = dataTable.Rows[i][TABLE_SCHEMA]; if (database.Equals($"{schema}", StringComparison.OrdinalIgnoreCase)) { var tableName = dataTable.Rows[i][TABLE_NAME]?.ToString() ?? string.Empty; if (tableName.StartsWith(CurrentTableName, StringComparison.OrdinalIgnoreCase)) { //如果没有下划线那么需要CurrentTableName.Length有下划线就要CurrentTableName.Length+1 _tails.TryAdd(tableName.Substring(CurrentTableName.Length + 1), null); } } } } } } public override string ShardingKeyToTail(object shardingKey) { return $"{shardingKey}"; } /// /// 如果你是非mysql数据库请自行实现这个方法返回当前类在数据库已经存在的后缀 /// 仅启动时调用 /// /// public override List GetTails() { if (!_inited) { lock(_initLock) { if (!_inited) { InitTails(); _inited = true; } } } return _tails.Keys.ToList(); } public override void Configure(EntityMetadataTableBuilder builder) { builder.ShardingProperty(o => o.Area); builder.TableSeparator(string.Empty); } public override Func GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator) { var t = ShardingKeyToTail(shardingKey); switch (shardingOperator) { case ShardingOperatorEnum.Equal: return tail => tail == t; default: { #if DEBUG Console.WriteLine($"shardingOperator is not equal scan all table tail"); #endif return tail => true; } } } public override TableRouteUnit RouteWithValue(DataSourceRouteResult dataSourceRouteResult, object shardingKey) { var shardingKeyToTail = ShardingKeyToTail(shardingKey); if (!_tails.TryGetValue(shardingKeyToTail, out var _)) { lock (_lock) { if (!_tails.TryGetValue(shardingKeyToTail, out var _)) { try { _tableCreator.CreateTable(_virtualDataSource.DefaultDataSourceName, shardingKeyToTail); } catch (Exception ex) { Console.WriteLine("尝试添加表失败" + ex); } _tails.TryAdd(shardingKeyToTail, null); } } } return base.RouteWithValue(dataSourceRouteResult, shardingKey); } } }