diff --git a/benchmarks/ShardingCoreBenchmark/EFCoreCrud.cs b/benchmarks/ShardingCoreBenchmark/EFCoreCrud.cs index 2ad0e8e8..99c95475 100644 --- a/benchmarks/ShardingCoreBenchmark/EFCoreCrud.cs +++ b/benchmarks/ShardingCoreBenchmark/EFCoreCrud.cs @@ -58,7 +58,6 @@ namespace ShardingCore6x { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; - o.AutoTrackEntity = false; }).AddShardingTransaction((connection, builder) => builder //.UseMySql(connection, new MySqlServerVersion(new Version())) .UseSqlServer(connection) diff --git a/benchmarks/ShardingCoreBenchmark/ShardingDbContexts/OrderVirtualTableRoute.cs b/benchmarks/ShardingCoreBenchmark/ShardingDbContexts/OrderVirtualTableRoute.cs index 9068704f..3fc4ed55 100644 --- a/benchmarks/ShardingCoreBenchmark/ShardingDbContexts/OrderVirtualTableRoute.cs +++ b/benchmarks/ShardingCoreBenchmark/ShardingDbContexts/OrderVirtualTableRoute.cs @@ -11,7 +11,7 @@ namespace ShardingCore6x.ShardingDbContexts { internal class OrderVirtualTableRoute:AbstractSimpleShardingModKeyStringVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public OrderVirtualTableRoute() : base(2, 5) { diff --git a/benchmarks/ShardingCoreBenchmark5x/EFCoreCrud.cs b/benchmarks/ShardingCoreBenchmark5x/EFCoreCrud.cs index f0b893fb..bc290029 100644 --- a/benchmarks/ShardingCoreBenchmark5x/EFCoreCrud.cs +++ b/benchmarks/ShardingCoreBenchmark5x/EFCoreCrud.cs @@ -39,7 +39,6 @@ namespace ShardingCoreBenchmark5x { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; - o.AutoTrackEntity = false; }).AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection)) .AddDefaultDataSource("ds0", "Data Source=localhost;Initial Catalog=db2;Integrated Security=True;") .AddShardingTableRoute(op => diff --git a/samples/Sample.BulkConsole/Program.cs b/samples/Sample.BulkConsole/Program.cs index 04bf146f..b96938f6 100644 --- a/samples/Sample.BulkConsole/Program.cs +++ b/samples/Sample.BulkConsole/Program.cs @@ -31,7 +31,6 @@ namespace Sample.BulkConsole { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; - o.AutoTrackEntity = true; }) .AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger)) diff --git a/samples/Sample.Migrations/DefaultDesignTimeDbContextFactory.cs b/samples/Sample.Migrations/DefaultDesignTimeDbContextFactory.cs index 2731fbe0..1e8c6677 100644 --- a/samples/Sample.Migrations/DefaultDesignTimeDbContextFactory.cs +++ b/samples/Sample.Migrations/DefaultDesignTimeDbContextFactory.cs @@ -26,7 +26,6 @@ namespace Sample.Migrations { o.CreateShardingTableOnStart = false; o.EnsureCreatedWithOutShardingTable = false; - o.AutoTrackEntity = true; }) .AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection)) diff --git a/samples/Sample.NoShardingMultiLevel/Program.cs b/samples/Sample.NoShardingMultiLevel/Program.cs index 659dea27..99520c05 100644 --- a/samples/Sample.NoShardingMultiLevel/Program.cs +++ b/samples/Sample.NoShardingMultiLevel/Program.cs @@ -19,7 +19,6 @@ builder.Services.AddControllers(); builder.Services.AddShardingDbContext((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger)) .Begin(o => { - o.AutoTrackEntity = true; o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; }) diff --git a/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs b/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs index 6e1567ad..34855b53 100644 --- a/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs +++ b/samples/Sample.SqlServer/Shardings/SysUserSalaryVirtualTableRoute.cs @@ -51,7 +51,7 @@ namespace Sample.SqlServer.Shardings return $"{dateOfMonth:yyyyMM}"; } - public override Expression> GetMainRouteFilter(int shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/samples/Sample.SqlServer/Shardings/TestVRoute.cs b/samples/Sample.SqlServer/Shardings/TestVRoute.cs index 62754143..9a57a4dc 100644 --- a/samples/Sample.SqlServer/Shardings/TestVRoute.cs +++ b/samples/Sample.SqlServer/Shardings/TestVRoute.cs @@ -30,7 +30,7 @@ namespace Sample.SqlServer.Shardings } - public override Expression> GetMainRouteFilter(string shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator) { var t = ShardingKeyToTail(shardingKey); switch (shardingOperator) diff --git a/samples/Sample.SqlServer/Startup.cs b/samples/Sample.SqlServer/Startup.cs index c9ff5fcd..67e04f82 100644 --- a/samples/Sample.SqlServer/Startup.cs +++ b/samples/Sample.SqlServer/Startup.cs @@ -36,7 +36,6 @@ namespace Sample.SqlServer { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; - o.AutoTrackEntity = true; o.MaxQueryConnectionsLimit = Environment.ProcessorCount; o.ConnectionMode = ConnectionModeEnum.SYSTEM_AUTO; //if SysTest entity not exists in db and db is exists diff --git a/samples/Sample.SqlServerShardingAll/Startup.cs b/samples/Sample.SqlServerShardingAll/Startup.cs index a54972c1..a1979a37 100644 --- a/samples/Sample.SqlServerShardingAll/Startup.cs +++ b/samples/Sample.SqlServerShardingAll/Startup.cs @@ -40,7 +40,6 @@ namespace Sample.SqlServerShardingAll builder.UseSqlServer(conStr).UseLoggerFactory(efLogger); }).Begin(op => { - op.AutoTrackEntity = true; //如果您使用code-first建议选择false op.CreateShardingTableOnStart = true; //如果您使用code-first建议修改为fsle diff --git a/samples/Sample.SqlServerShardingDataSource/Startup.cs b/samples/Sample.SqlServerShardingDataSource/Startup.cs index 2f28cc8d..5748f7e3 100644 --- a/samples/Sample.SqlServerShardingDataSource/Startup.cs +++ b/samples/Sample.SqlServerShardingDataSource/Startup.cs @@ -36,7 +36,6 @@ namespace Sample.SqlServerShardingDataSource builder.UseSqlServer(conStr).UseLoggerFactory(efLogger); }).Begin(op => { - op.AutoTrackEntity = true; //如果您使用code-first建议选择false op.CreateShardingTableOnStart = true; //如果您使用code-first建议修改为false diff --git a/samples/Sample.SqlServerShardingTable/Common/IdHelper.cs b/samples/Sample.SqlServerShardingTable/Common/IdHelper.cs new file mode 100644 index 00000000..6e247e00 --- /dev/null +++ b/samples/Sample.SqlServerShardingTable/Common/IdHelper.cs @@ -0,0 +1,25 @@ +锘縰sing System; + +namespace Sample.SqlServerShardingTable.Common +{ + public class IdHelper + { + private IdHelper(){} + private static SnowflakeId _snowflakeId; + + static IdHelper() + { + _snowflakeId = new SnowflakeId(1,3); + } + + public static long NextId() + { + return _snowflakeId.NextId(); + } + + public static DateTime FromId(long id) + { + return SnowflakeId.AnalyzeIdToDateTime(id); + } + } +} diff --git a/samples/Sample.SqlServerShardingTable/Common/SnowflakeId.cs b/samples/Sample.SqlServerShardingTable/Common/SnowflakeId.cs new file mode 100644 index 00000000..d9b34897 --- /dev/null +++ b/samples/Sample.SqlServerShardingTable/Common/SnowflakeId.cs @@ -0,0 +1,196 @@ +锘縰sing System; +using System.Text; + +namespace Sample.SqlServerShardingTable.Common +{/// + /// 闆姳ID + /// Twitter_Snowflake + /// SnowFlake鐨勭粨鏋勫涓(姣忛儴鍒嗙敤-鍒嗗紑) + /// 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 + /// 1浣嶆爣璇嗭紝鐢变簬long鍩烘湰绫诲瀷鍦↗ava涓槸甯︾鍙风殑锛屾渶楂樹綅鏄鍙蜂綅锛屾鏁版槸0锛岃礋鏁版槸1锛屾墍浠d涓鑸槸姝f暟锛屾渶楂樹綅鏄0 + /// 41浣嶆椂闂存埅(姣绾)锛屾敞鎰忥紝41浣嶆椂闂存埅涓嶆槸瀛樺偍褰撳墠鏃堕棿鐨勬椂闂存埅锛岃屾槸瀛樺偍鏃堕棿鎴殑宸硷紙褰撳墠鏃堕棿鎴 - 寮濮嬫椂闂存埅)寰楀埌鐨勫硷級锛 + /// 41浣嶇殑鏃堕棿鎴紝鍙互浣跨敤69骞达紝骞碩 = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 + /// 杩欓噷鐨勭殑寮濮嬫椂闂存埅锛屼竴鑸槸鎴戜滑鐨刬d鐢熸垚鍣ㄥ紑濮嬩娇鐢ㄧ殑鏃堕棿锛岀敱鎴戜滑绋嬪簭鏉ユ寚瀹氱殑锛堝涓嬩笅闈㈢▼搴廔dWorker绫荤殑startTime灞炴э級銆 + /// 10浣嶇殑鏁版嵁鏈哄櫒浣嶏紝鍙互閮ㄧ讲鍦1024涓妭鐐癸紝鍖呮嫭5浣峝atacenterId鍜5浣峸orkerId + /// 12浣嶅簭鍒楋紝姣鍐呯殑璁℃暟锛12浣嶇殑璁℃暟椤哄簭鍙锋敮鎸佹瘡涓妭鐐规瘡姣(鍚屼竴鏈哄櫒锛屽悓涓鏃堕棿鎴)浜х敓4096涓狪D搴忓彿 + /// 鎬诲叡鍔犺捣鏉ュ垰濂64浣嶏紝涓轰竴涓狶ong鍨嬨 + /// SnowFlake鐨勪紭鐐规槸锛屾暣浣撲笂鎸夌収鏃堕棿鑷鎺掑簭锛屽苟涓旀暣涓垎甯冨紡绯荤粺鍐呬笉浼氫骇鐢烮D纰版挒(鐢辨暟鎹腑蹇僆D鍜屾満鍣↖D浣滃尯鍒)锛 + /// 骞朵笖鏁堢巼杈冮珮锛岀粡娴嬭瘯锛孲nowFlake鍗曟満姣忕閮借兘澶熶骇鐢熷嚭鏋侀檺4,096,000涓狪D鏉 + /// + public class SnowflakeId + { + + // 寮濮嬫椂闂存埅 (new DateTime(2020, 1, 1).ToUniversalTime() - Jan1st1970).TotalMilliseconds + private const long twepoch = 1577808000000L; + + // 鏈哄櫒id鎵鍗犵殑浣嶆暟 + private const int workerIdBits = 5; + + // 鏁版嵁鏍囪瘑id鎵鍗犵殑浣嶆暟 + private const int datacenterIdBits = 5; + + // 鏀寔鐨勬渶澶ф満鍣╥d锛岀粨鏋滄槸31 (杩欎釜绉讳綅绠楁硶鍙互寰堝揩鐨勮绠楀嚭鍑犱綅浜岃繘鍒舵暟鎵鑳借〃绀虹殑鏈澶у崄杩涘埗鏁) + private const long maxWorkerId = -1L ^ (-1L << workerIdBits); + + // 鏀寔鐨勬渶澶ф暟鎹爣璇唅d锛岀粨鏋滄槸31 + private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + // 搴忓垪鍦╥d涓崰鐨勪綅鏁 + private const int sequenceBits = 12; + + // 鏁版嵁鏍囪瘑id鍚戝乏绉17浣(12+5) + private const int datacenterIdShift = sequenceBits + workerIdBits; + + // 鏈哄櫒ID鍚戝乏绉12浣 + private const int workerIdShift = sequenceBits; + + + // 鏃堕棿鎴悜宸︾Щ22浣(5+5+12) + private const int timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + // 鐢熸垚搴忓垪鐨勬帺鐮侊紝杩欓噷涓4095 (0b111111111111=0xfff=4095) + private const long sequenceMask = -1L ^ (-1L << sequenceBits); + + // 鏁版嵁涓績ID(0~31) + public long datacenterId { get; private set; } + + // 宸ヤ綔鏈哄櫒ID(0~31) + public long workerId { get; private set; } + + // 姣鍐呭簭鍒(0~4095) + public long sequence { get; private set; } + + // 涓婃鐢熸垚ID鐨勬椂闂存埅 + public long lastTimestamp { get; private set; } + + + /// + /// 闆姳ID + /// + /// 鏁版嵁涓績ID + /// 宸ヤ綔鏈哄櫒ID + public SnowflakeId(long datacenterId, long workerId) + { + if (datacenterId > maxDatacenterId || datacenterId < 0) + { + throw new Exception(string.Format("datacenter Id can't be greater than {0} or less than 0", maxDatacenterId)); + } + if (workerId > maxWorkerId || workerId < 0) + { + throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", maxWorkerId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + this.sequence = 0L; + this.lastTimestamp = -1L; + } + + /// + /// 鑾峰緱涓嬩竴涓狪D + /// + /// + public long NextId() + { + lock (this) + { + long timestamp = GetCurrentTimestamp(); + if (timestamp > lastTimestamp) //鏃堕棿鎴虫敼鍙橈紝姣鍐呭簭鍒楅噸缃 + { + sequence = 0L; + } + else if (timestamp == lastTimestamp) //濡傛灉鏄悓涓鏃堕棿鐢熸垚鐨勶紝鍒欒繘琛屾绉掑唴搴忓垪 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) //姣鍐呭簭鍒楁孩鍑 + { + timestamp = GetNextTimestamp(lastTimestamp); //闃诲鍒颁笅涓涓绉,鑾峰緱鏂扮殑鏃堕棿鎴 + } + } + else //褰撳墠鏃堕棿灏忎簬涓婁竴娆D鐢熸垚鐨勬椂闂存埑锛岃瘉鏄庣郴缁熸椂閽熻鍥炴嫧锛屾鏃堕渶瑕佸仛鍥炴嫧澶勭悊 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence > 0) + { + timestamp = lastTimestamp; //鍋滅暀鍦ㄦ渶鍚庝竴娆℃椂闂存埑涓婏紝绛夊緟绯荤粺鏃堕棿杩戒笂鍚庡嵆瀹屽叏搴﹁繃浜嗘椂閽熷洖鎷ㄩ棶棰樸 + } + else //姣鍐呭簭鍒楁孩鍑 + { + timestamp = lastTimestamp + 1; //鐩存帴杩涗綅鍒颁笅涓涓绉 + } + //throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp)); + } + + lastTimestamp = timestamp; //涓婃鐢熸垚ID鐨勬椂闂存埅 + + //绉讳綅骞堕氳繃鎴栬繍绠楁嫾鍒颁竴璧风粍鎴64浣嶇殑ID + var id = ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + return id; + } + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static DateTime AnalyzeIdToDateTime(long Id) + { + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + return time.ToLocalTime(); + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static string AnalyzeId(long Id) + { + StringBuilder sb = new StringBuilder(); + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + sb.Append(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss:fff")); + + var datacenterId = (Id ^ (timestamp << timestampLeftShift)) >> datacenterIdShift; + sb.Append("_" + datacenterId); + + var workerId = (Id ^ ((timestamp << timestampLeftShift) | (datacenterId << datacenterIdShift))) >> workerIdShift; + sb.Append("_" + workerId); + + var sequence = Id & sequenceMask; + sb.Append("_" + sequence); + + return sb.ToString(); + } + + /// + /// 闃诲鍒颁笅涓涓绉掞紝鐩村埌鑾峰緱鏂扮殑鏃堕棿鎴 + /// + /// 涓婃鐢熸垚ID鐨勬椂闂存埅 + /// 褰撳墠鏃堕棿鎴 + private static long GetNextTimestamp(long lastTimestamp) + { + long timestamp = GetCurrentTimestamp(); + while (timestamp <= lastTimestamp) + { + timestamp = GetCurrentTimestamp(); + } + return timestamp; + } + + /// + /// 鑾峰彇褰撳墠鏃堕棿鎴 + /// + /// + private static long GetCurrentTimestamp() + { + return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds; + } + + private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + } +} diff --git a/samples/Sample.SqlServerShardingTable/Common/SnowflakeIdMock.cs b/samples/Sample.SqlServerShardingTable/Common/SnowflakeIdMock.cs new file mode 100644 index 00000000..0b73209f --- /dev/null +++ b/samples/Sample.SqlServerShardingTable/Common/SnowflakeIdMock.cs @@ -0,0 +1,196 @@ +锘縰sing System; +using System.Text; + +namespace Sample.SqlServerShardingTable.Common +{/// + /// 闆姳ID + /// Twitter_Snowflake + /// SnowFlake鐨勭粨鏋勫涓(姣忛儴鍒嗙敤-鍒嗗紑) + /// 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 + /// 1浣嶆爣璇嗭紝鐢变簬long鍩烘湰绫诲瀷鍦↗ava涓槸甯︾鍙风殑锛屾渶楂樹綅鏄鍙蜂綅锛屾鏁版槸0锛岃礋鏁版槸1锛屾墍浠d涓鑸槸姝f暟锛屾渶楂樹綅鏄0 + /// 41浣嶆椂闂存埅(姣绾)锛屾敞鎰忥紝41浣嶆椂闂存埅涓嶆槸瀛樺偍褰撳墠鏃堕棿鐨勬椂闂存埅锛岃屾槸瀛樺偍鏃堕棿鎴殑宸硷紙褰撳墠鏃堕棿鎴 - 寮濮嬫椂闂存埅)寰楀埌鐨勫硷級锛 + /// 41浣嶇殑鏃堕棿鎴紝鍙互浣跨敤69骞达紝骞碩 = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 + /// 杩欓噷鐨勭殑寮濮嬫椂闂存埅锛屼竴鑸槸鎴戜滑鐨刬d鐢熸垚鍣ㄥ紑濮嬩娇鐢ㄧ殑鏃堕棿锛岀敱鎴戜滑绋嬪簭鏉ユ寚瀹氱殑锛堝涓嬩笅闈㈢▼搴廔dWorker绫荤殑startTime灞炴э級銆 + /// 10浣嶇殑鏁版嵁鏈哄櫒浣嶏紝鍙互閮ㄧ讲鍦1024涓妭鐐癸紝鍖呮嫭5浣峝atacenterId鍜5浣峸orkerId + /// 12浣嶅簭鍒楋紝姣鍐呯殑璁℃暟锛12浣嶇殑璁℃暟椤哄簭鍙锋敮鎸佹瘡涓妭鐐规瘡姣(鍚屼竴鏈哄櫒锛屽悓涓鏃堕棿鎴)浜х敓4096涓狪D搴忓彿 + /// 鎬诲叡鍔犺捣鏉ュ垰濂64浣嶏紝涓轰竴涓狶ong鍨嬨 + /// SnowFlake鐨勪紭鐐规槸锛屾暣浣撲笂鎸夌収鏃堕棿鑷鎺掑簭锛屽苟涓旀暣涓垎甯冨紡绯荤粺鍐呬笉浼氫骇鐢烮D纰版挒(鐢辨暟鎹腑蹇僆D鍜屾満鍣↖D浣滃尯鍒)锛 + /// 骞朵笖鏁堢巼杈冮珮锛岀粡娴嬭瘯锛孲nowFlake鍗曟満姣忕閮借兘澶熶骇鐢熷嚭鏋侀檺4,096,000涓狪D鏉 + /// + public class SnowflakeIdMock + { + + // 寮濮嬫椂闂存埅 (new DateTime(2020, 1, 1).ToUniversalTime() - Jan1st1970).TotalMilliseconds + private const long twepoch = 1577808000000L; + + // 鏈哄櫒id鎵鍗犵殑浣嶆暟 + private const int workerIdBits = 5; + + // 鏁版嵁鏍囪瘑id鎵鍗犵殑浣嶆暟 + private const int datacenterIdBits = 5; + + // 鏀寔鐨勬渶澶ф満鍣╥d锛岀粨鏋滄槸31 (杩欎釜绉讳綅绠楁硶鍙互寰堝揩鐨勮绠楀嚭鍑犱綅浜岃繘鍒舵暟鎵鑳借〃绀虹殑鏈澶у崄杩涘埗鏁) + private const long maxWorkerId = -1L ^ (-1L << workerIdBits); + + // 鏀寔鐨勬渶澶ф暟鎹爣璇唅d锛岀粨鏋滄槸31 + private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + // 搴忓垪鍦╥d涓崰鐨勪綅鏁 + private const int sequenceBits = 12; + + // 鏁版嵁鏍囪瘑id鍚戝乏绉17浣(12+5) + private const int datacenterIdShift = sequenceBits + workerIdBits; + + // 鏈哄櫒ID鍚戝乏绉12浣 + private const int workerIdShift = sequenceBits; + + + // 鏃堕棿鎴悜宸︾Щ22浣(5+5+12) + private const int timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + // 鐢熸垚搴忓垪鐨勬帺鐮侊紝杩欓噷涓4095 (0b111111111111=0xfff=4095) + private const long sequenceMask = -1L ^ (-1L << sequenceBits); + + // 鏁版嵁涓績ID(0~31) + public long datacenterId { get; private set; } + + // 宸ヤ綔鏈哄櫒ID(0~31) + public long workerId { get; private set; } + + // 姣鍐呭簭鍒(0~4095) + public long sequence { get; private set; } + + // 涓婃鐢熸垚ID鐨勬椂闂存埅 + public long lastTimestamp { get; private set; } + + + /// + /// 闆姳ID + /// + /// 鏁版嵁涓績ID + /// 宸ヤ綔鏈哄櫒ID + public SnowflakeIdMock(long datacenterId, long workerId) + { + if (datacenterId > maxDatacenterId || datacenterId < 0) + { + throw new Exception(string.Format("datacenter Id can't be greater than {0} or less than 0", maxDatacenterId)); + } + if (workerId > maxWorkerId || workerId < 0) + { + throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", maxWorkerId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + this.sequence = 0L; + this.lastTimestamp = -1L; + } + + /// + /// 鑾峰緱涓嬩竴涓狪D + /// + /// + public long NextId(DateTime utc) + { + lock (this) + { + long timestamp = GetCurrentTimestamp(utc); + if (timestamp > lastTimestamp) //鏃堕棿鎴虫敼鍙橈紝姣鍐呭簭鍒楅噸缃 + { + sequence = 0L; + } + else if (timestamp == lastTimestamp) //濡傛灉鏄悓涓鏃堕棿鐢熸垚鐨勶紝鍒欒繘琛屾绉掑唴搴忓垪 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) //姣鍐呭簭鍒楁孩鍑 + { + timestamp = GetNextTimestamp(lastTimestamp, utc); //闃诲鍒颁笅涓涓绉,鑾峰緱鏂扮殑鏃堕棿鎴 + } + } + else //褰撳墠鏃堕棿灏忎簬涓婁竴娆D鐢熸垚鐨勬椂闂存埑锛岃瘉鏄庣郴缁熸椂閽熻鍥炴嫧锛屾鏃堕渶瑕佸仛鍥炴嫧澶勭悊 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence > 0) + { + timestamp = lastTimestamp; //鍋滅暀鍦ㄦ渶鍚庝竴娆℃椂闂存埑涓婏紝绛夊緟绯荤粺鏃堕棿杩戒笂鍚庡嵆瀹屽叏搴﹁繃浜嗘椂閽熷洖鎷ㄩ棶棰樸 + } + else //姣鍐呭簭鍒楁孩鍑 + { + timestamp = lastTimestamp + 1; //鐩存帴杩涗綅鍒颁笅涓涓绉 + } + //throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp)); + } + + lastTimestamp = timestamp; //涓婃鐢熸垚ID鐨勬椂闂存埅 + + //绉讳綅骞堕氳繃鎴栬繍绠楁嫾鍒颁竴璧风粍鎴64浣嶇殑ID + var id = ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + return id; + } + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static DateTime AnalyzeIdToDateTime(long Id) + { + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + return time.ToLocalTime(); + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static string AnalyzeId(long Id) + { + StringBuilder sb = new StringBuilder(); + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + sb.Append(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss:fff")); + + var datacenterId = (Id ^ (timestamp << timestampLeftShift)) >> datacenterIdShift; + sb.Append("_" + datacenterId); + + var workerId = (Id ^ ((timestamp << timestampLeftShift) | (datacenterId << datacenterIdShift))) >> workerIdShift; + sb.Append("_" + workerId); + + var sequence = Id & sequenceMask; + sb.Append("_" + sequence); + + return sb.ToString(); + } + + /// + /// 闃诲鍒颁笅涓涓绉掞紝鐩村埌鑾峰緱鏂扮殑鏃堕棿鎴 + /// + /// 涓婃鐢熸垚ID鐨勬椂闂存埅 + /// 褰撳墠鏃堕棿鎴 + private static long GetNextTimestamp(long lastTimestamp, DateTime utc) + { + long timestamp = GetCurrentTimestamp(utc); + while (timestamp <= lastTimestamp) + { + timestamp = GetCurrentTimestamp(utc); + } + return timestamp; + } + + /// + /// 鑾峰彇褰撳墠鏃堕棿鎴 + /// + /// + private static long GetCurrentTimestamp(DateTime utc) + { + return (long)(utc - Jan1st1970).TotalMilliseconds; + } + + private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + } +} diff --git a/samples/Sample.SqlServerShardingTable/Controllers/TestController.cs b/samples/Sample.SqlServerShardingTable/Controllers/TestController.cs index e31b6d95..f5944e3c 100644 --- a/samples/Sample.SqlServerShardingTable/Controllers/TestController.cs +++ b/samples/Sample.SqlServerShardingTable/Controllers/TestController.cs @@ -34,6 +34,21 @@ namespace Sample.SqlServerShardingTable.Controllers sysUsers }); } + public async Task Query2() + { + var multiOrder =await _myDbContext.Set().Where(o=>o.Id== 232398109278351360).FirstOrDefaultAsync(); + var longs = new []{ 232398109278351360 , 255197859283087360 }; + var multiOrders = await _myDbContext.Set().Where(o => longs.Contains(o.Id)).ToListAsync(); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = await _myDbContext.Set().Where(o => o.Id == 250345338962063360&&o.CreateTime< dateTime).FirstOrDefaultAsync(); + return Ok(new + { + multiOrder, + multiOrders, + multiOrder404 + }); + + } public async Task QueryJoin1() { var sql= from user in _myDbContext.Set().Where(o => o.Id == "1" || o.Id == "6") diff --git a/samples/Sample.SqlServerShardingTable/Entities/MultiShardingOrder.cs b/samples/Sample.SqlServerShardingTable/Entities/MultiShardingOrder.cs new file mode 100644 index 00000000..646f57de --- /dev/null +++ b/samples/Sample.SqlServerShardingTable/Entities/MultiShardingOrder.cs @@ -0,0 +1,11 @@ +锘縰sing System; + +namespace Sample.SqlServerShardingTable.Entities +{ + public class MultiShardingOrder + { + public long Id { get; set; } + public string Name { get; set; } + public DateTime CreateTime { get; set; } + } +} diff --git a/samples/Sample.SqlServerShardingTable/MyDbContext.cs b/samples/Sample.SqlServerShardingTable/MyDbContext.cs index 3f70d22e..6163738f 100644 --- a/samples/Sample.SqlServerShardingTable/MyDbContext.cs +++ b/samples/Sample.SqlServerShardingTable/MyDbContext.cs @@ -40,6 +40,13 @@ namespace Sample.SqlServerShardingTable entity.Property(o=>o.Name).IsRequired().IsUnicode(false).HasMaxLength(50); entity.ToTable(nameof(Setting)); }); + modelBuilder.Entity(entity => + { + entity.HasKey(o => o.Id); + entity.Property(o => o.Id).ValueGeneratedNever(); + entity.Property(o=>o.Name).IsRequired().IsUnicode(false).HasMaxLength(50); + entity.ToTable(nameof(MultiShardingOrder)); + }); } /// /// empty impl diff --git a/samples/Sample.SqlServerShardingTable/Startup.cs b/samples/Sample.SqlServerShardingTable/Startup.cs index 5b8e7996..4a2d4d65 100644 --- a/samples/Sample.SqlServerShardingTable/Startup.cs +++ b/samples/Sample.SqlServerShardingTable/Startup.cs @@ -38,11 +38,12 @@ namespace Sample.SqlServerShardingTable builder.UseSqlServer(conStr).UseLoggerFactory(efLogger); }).Begin(op => { - op.AutoTrackEntity = true; //如果您使用code-first建议选择false op.CreateShardingTableOnStart = true; //如果您使用code-first建议修改为fsle op.EnsureCreatedWithOutShardingTable = true; + //当无法获取路由时会返回默认值而不是报错 + op.ThrowIfQueryRouteNotMatch = false; }).AddShardingTransaction((connection, builder) => { builder.UseSqlServer(connection).UseLoggerFactory(efLogger); @@ -52,6 +53,7 @@ namespace Sample.SqlServerShardingTable { op.AddShardingTableRoute(); op.AddShardingTableRoute(); + op.AddShardingTableRoute(); }).End(); } diff --git a/samples/Sample.SqlServerShardingTable/StartupExtension.cs b/samples/Sample.SqlServerShardingTable/StartupExtension.cs index d5282f9a..2564e90f 100644 --- a/samples/Sample.SqlServerShardingTable/StartupExtension.cs +++ b/samples/Sample.SqlServerShardingTable/StartupExtension.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; +using Sample.SqlServerShardingTable.Common; using Sample.SqlServerShardingTable.Entities; using ShardingCore.Bootstrapers; @@ -66,9 +67,88 @@ namespace Sample.SqlServerShardingTable }; orders.Add(order); } + + var multiShardingOrders = new List(9); + #region 娣诲姞澶氬瓧娈靛垎琛 + + { + var now = new DateTime(2021, 10, 1, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 231765457240207360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 2, 11, 3, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232095129534607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 3, 7, 7, 7); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232398109278351360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 6, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 244811420401807360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 21, 19, 43, 0); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 250345338962063360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 5, 5, 5, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 255197859283087360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 9, 19, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 256860816933007360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 19, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 260394098622607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + #endregion + myDbContext.AddRange(settings); myDbContext.AddRange(users); myDbContext.AddRange(orders); + myDbContext.AddRange(multiShardingOrders); myDbContext.SaveChanges(); } } diff --git a/samples/Sample.SqlServerShardingTable/VirtualRoutes/MultiShardingOrderVirtualTableRoute.cs b/samples/Sample.SqlServerShardingTable/VirtualRoutes/MultiShardingOrderVirtualTableRoute.cs new file mode 100644 index 00000000..18a86df5 --- /dev/null +++ b/samples/Sample.SqlServerShardingTable/VirtualRoutes/MultiShardingOrderVirtualTableRoute.cs @@ -0,0 +1,79 @@ +锘縰sing System; +using System.Linq.Expressions; +using Sample.SqlServerShardingTable.Common; +using Sample.SqlServerShardingTable.Entities; +using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Helpers; +using ShardingCore.VirtualRoutes.Months; + +namespace Sample.SqlServerShardingTable.VirtualRoutes +{ + public class MultiShardingOrderVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute + { + public override void Configure(EntityMetadataTableBuilder builder) + { + builder.ShardingProperty(o => o.CreateTime); + builder.ShardingExtraProperty(o => o.Id); + } + + public override Expression> GetExtraRouteFilter(object shardingKey, ShardingOperatorEnum shardingOperator, string shardingPropertyName) + { + switch (shardingPropertyName) + { + case nameof(MultiShardingOrder.Id): return GetIdRouteFilter(shardingKey, shardingOperator); + default: throw new NotImplementedException(shardingPropertyName); + } + } + + private Expression> GetIdRouteFilter(object shardingKey, + ShardingOperatorEnum shardingOperator) + { + //瑙f瀽闆姳id 闇瑕佽冭檻寮傚父鎯呭喌,浼犲叆鐨勫彲鑳戒笉鏄洩鑺眎d閭d箞鍙互闅忔満鏌ヨ涓寮犺〃 + var analyzeIdToDateTime = SnowflakeId.AnalyzeIdToDateTime(Convert.ToInt64(shardingKey)); + //褰撳墠鏃堕棿鐨則ail + var t = TimeFormatToTail(analyzeIdToDateTime); + //鍥犱负鏄寜鏈堝垎琛ㄦ墍浠ヨ幏鍙栦笅涓湀鐨勬椂闂村垽鏂璱d鏄惁鏄湪鐏电晫鐐瑰垱寤虹殑 + var nextMonthFirstDay = ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(10) > nextMonthFirstDay) + { + var nextT = TimeFormatToTail(nextMonthFirstDay); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t||tail== nextT; + } + } + var currentMonthFirstDay = ShardingCoreHelper.GetCurrentMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(-10) < currentMonthFirstDay) + { + //涓婁釜鏈坱ail + var nextT = TimeFormatToTail(analyzeIdToDateTime.AddSeconds(-10)); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t || tail == nextT; + } + } + else + { + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t; + } + } + + return tail => true; + } + + public override bool AutoCreateTableByTime() + { + return true; + } + + public override DateTime GetBeginTime() + { + return new DateTime(2021, 9, 1); + } + } +} diff --git a/samples/Sample.SqlServerShardingTable/VirtualRoutes/OrderHashRangeVirtualTableRoute.cs b/samples/Sample.SqlServerShardingTable/VirtualRoutes/OrderHashRangeVirtualTableRoute.cs index 69612325..9f994dbc 100644 --- a/samples/Sample.SqlServerShardingTable/VirtualRoutes/OrderHashRangeVirtualTableRoute.cs +++ b/samples/Sample.SqlServerShardingTable/VirtualRoutes/OrderHashRangeVirtualTableRoute.cs @@ -48,7 +48,7 @@ namespace Sample.SqlServerShardingTable.VirtualRoutes } - public override Expression> GetMainRouteFilter(string shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator) { //鍥犱负hash璺敱浠呮敮鎸佺瓑浜庢墍浠ヤ粎浠呭彧闇瑕佸啓绛変簬鐨勬儏鍐 var t = ShardingKeyToTail(shardingKey); diff --git a/src/ShardingCore/Core/EntityMetadatas/EntityMetadataDataSourceBuilder.cs b/src/ShardingCore/Core/EntityMetadatas/EntityMetadataDataSourceBuilder.cs index c0b5c8b2..09289bb3 100644 --- a/src/ShardingCore/Core/EntityMetadatas/EntityMetadataDataSourceBuilder.cs +++ b/src/ShardingCore/Core/EntityMetadatas/EntityMetadataDataSourceBuilder.cs @@ -41,6 +41,18 @@ namespace ShardingCore.Core.EntityMetadatas _entityMetadata.SetShardingDataSourceProperty(propertyInfo); return this; } + public EntityMetadataDataSourceBuilder ShardingExtraProperty(Expression> propertyExpression) + { + var propertyAccess = propertyExpression.GetPropertyAccess(); + _entityMetadata.AddExtraSharingDataSourceProperty(propertyAccess); + return this; + } + public EntityMetadataDataSourceBuilder ShardingExtraProperty(string propertyName) + { + var propertyInfo = typeof(TEntity).GetProperty(propertyName); + _entityMetadata.AddExtraSharingDataSourceProperty(propertyInfo); + return this; + } /// /// 鏄惁鍚姩寤鸿〃 /// diff --git a/src/ShardingCore/Core/EntityMetadatas/EntityMetadataTableBuilder.cs b/src/ShardingCore/Core/EntityMetadatas/EntityMetadataTableBuilder.cs index d4d51104..6c79d482 100644 --- a/src/ShardingCore/Core/EntityMetadatas/EntityMetadataTableBuilder.cs +++ b/src/ShardingCore/Core/EntityMetadatas/EntityMetadataTableBuilder.cs @@ -38,6 +38,18 @@ namespace ShardingCore.Core.EntityMetadatas _entityMetadata.SetShardingTableProperty(propertyInfo); return this; } + public EntityMetadataTableBuilder ShardingExtraProperty(Expression> propertyExpression) + { + var propertyAccess = propertyExpression.GetPropertyAccess(); + _entityMetadata.AddExtraSharingTableProperty(propertyAccess); + return this; + } + public EntityMetadataTableBuilder ShardingExtraProperty(string propertyName) + { + var propertyInfo = typeof(TEntity).GetProperty(propertyName); + _entityMetadata.AddExtraSharingTableProperty(propertyInfo); + return this; + } /// /// 鍒嗚〃琛ㄥ拰鍚庣紑杩炴帴鍣 /// diff --git a/src/ShardingCore/Core/TrackerManagers/TrackerManager.cs b/src/ShardingCore/Core/TrackerManagers/TrackerManager.cs index 1afc4549..ad904408 100644 --- a/src/ShardingCore/Core/TrackerManagers/TrackerManager.cs +++ b/src/ShardingCore/Core/TrackerManagers/TrackerManager.cs @@ -16,13 +16,8 @@ namespace ShardingCore.Core.TrackerManagers */ public class TrackerManager: ITrackerManager where TShardingDbContext : DbContext, IShardingDbContext { - private readonly IShardingConfigOption _shardingConfigOption; private readonly ISet _dbContextModels = new HashSet(); - public TrackerManager(IShardingConfigOption shardingConfigOption) - { - _shardingConfigOption = shardingConfigOption; - } public bool AddDbContextModel(Type entityType) { return _dbContextModels.Add(entityType); @@ -30,8 +25,6 @@ namespace ShardingCore.Core.TrackerManagers public bool EntityUseTrack(Type entityType) { - if (!_shardingConfigOption.AutoTrackEntity) - return false; return _dbContextModels.Contains(entityType); } diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute.cs index 5e9fbfff..d71f10c2 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute.cs @@ -18,7 +18,6 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions public abstract class AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute : AbstractShardingFilterVirtualDataSourceRoute where TEntity : class { private static readonly ConcurrentDictionary>, Func> _routeCompileCaches = new(new ExtensionExpressionComparer.RouteParseExpressionEqualityComparer()); - static AbstractShardingRouteParseCompileCacheVirtualDataSourceRoute() { Expression> defaultWhere1 = x => true; @@ -30,7 +29,14 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions /// /// 鏄惁鍚敤璺敱瑙f瀽缂栬瘧缂撳瓨 /// - public virtual bool EnableRouteParseCompileCache => false; + public virtual bool? EnableRouteParseCompileCache => null; + + public virtual bool EnableCompileCache() + { + if (EnableRouteParseCompileCache.HasValue) + return EnableRouteParseCompileCache.Value; + return ShardingConfigOption.EnableDataSourceRouteCompileCache.GetValueOrDefault(); + } /// /// 瀵硅〃杈惧紡杩涜缂撳瓨缂栬瘧榛樿姘镐箙缂撳瓨鍗曚釜鍙傛暟琛ㄨ揪寮忥紝涓斾笉鍖呭惈orElse鍙寘鍚崟涓狝ndAlso鎴栬呮病鏈堿ndAlso鐨, @@ -41,7 +47,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions /// public virtual Func CachingCompile(Expression> parseWhere) { - if (EnableRouteParseCompileCache) + if (EnableCompileCache()) { var doCachingCompile = DoCachingCompile(parseWhere); if (doCachingCompile != null) diff --git a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractVirtualDataSourceRoute.cs b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractVirtualDataSourceRoute.cs index 61c4866d..627d7a7b 100644 --- a/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractVirtualDataSourceRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/DataSourceRoutes/Abstractions/AbstractVirtualDataSourceRoute.cs @@ -19,6 +19,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions { public EntityMetadata EntityMetadata { get; private set; } private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce(); + public IShardingConfigOption ShardingConfigOption { get; private set; } public void Initialize(EntityMetadata entityMetadata) @@ -34,6 +35,9 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.Abstractions paginationConfiguration.Configure(paginationBuilder); } + ShardingConfigOption = + ShardingContainer.GetRequiredShardingConfigOption(entityMetadata.ShardingDbContextType); + } public virtual IPaginationConfiguration CreatePaginationConfiguration() { diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingOperatorVirtualTableRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingOperatorVirtualTableRoute.cs index 89f924b3..d36fc3a8 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingOperatorVirtualTableRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingOperatorVirtualTableRoute.cs @@ -21,7 +21,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions protected override List DoRouteWithPredicate(List allPhysicTables, IQueryable queryable) { //鑾峰彇璺敱鍚庣紑琛ㄨ揪寮 - var routeParseExpression = ShardingUtil.GetRouteParseExpression(queryable, EntityMetadata, GetRouteToFilter,true); + var routeParseExpression = ShardingUtil.GetRouteParseExpression(queryable, EntityMetadata, GetRouteFilter,true); //琛ㄨ揪寮忕紦瀛樼紪璇 var filter =CachingCompile(routeParseExpression); //閫氳繃缂栬瘧缁撴灉杩涜杩囨护 @@ -37,12 +37,12 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions /// 鎿嶄綔 /// 鍒嗚〃瀛楁 /// 濡傛灉杩斿洖true琛ㄧず杩斿洖璇ヨ〃 绗竴涓弬鏁 tail 绗簩鍙傛暟鏄惁杩斿洖璇ョ墿鐞嗚〃 - public Expression> GetRouteToFilter(object shardingKey, + public Expression> GetRouteFilter(object shardingKey, ShardingOperatorEnum shardingOperator, string shardingPropertyName) { if (EntityMetadata.IsMainShardingTableKey(shardingPropertyName)) { - return GetMainRouteFilter((TKey)shardingKey, shardingOperator); + return GetRouteToFilter((TKey)shardingKey, shardingOperator); } else { @@ -50,7 +50,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions } } - public abstract Expression> GetMainRouteFilter(TKey shardingKey, + public abstract Expression> GetRouteToFilter(TKey shardingKey, ShardingOperatorEnum shardingOperator); public virtual Expression> GetExtraRouteFilter(object shardingKey, diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualTableRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualTableRoute.cs index 001d72ed..d19b34cd 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualTableRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractShardingRouteParseCompileCacheVirtualTableRoute.cs @@ -32,7 +32,13 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions /// /// 鏄惁鍚敤璺敱瑙f瀽缂栬瘧缂撳瓨 /// - public virtual bool EnableRouteParseCompileCache => false; + public virtual bool? EnableRouteParseCompileCache => null; + public virtual bool EnableCompileCache() + { + if (EnableRouteParseCompileCache.HasValue) + return EnableRouteParseCompileCache.Value; + return ShardingConfigOption.EnableTableRouteCompileCache.GetValueOrDefault(); + } /// /// 瀵硅〃杈惧紡杩涜缂撳瓨缂栬瘧榛樿姘镐箙缂撳瓨鍗曚釜鍙傛暟琛ㄨ揪寮忥紝涓斾笉鍖呭惈orElse鍙寘鍚崟涓狝ndAlso鎴栬呮病鏈堿ndAlso鐨, /// 姣斿:鎴栬x]]>,涓嶄細缂撳瓨id>x && o.id绛変竴鍏卞ぇ浜庛佺瓑浜庛佸皬浜庛佸ぇ浜庣瓑浜庛佸皬浜庣瓑浜(涓嶇瓑浜庣紪璇戞垚true]]>)缂撳瓨浼氬瓨鍦ㄧ殑鏁伴噺涓暟涓婇檺涓 @@ -42,7 +48,7 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions /// public virtual Func CachingCompile(Expression> parseWhere) { - if (EnableRouteParseCompileCache) + if (EnableCompileCache()) { var doCachingCompile = DoCachingCompile(parseWhere); if (doCachingCompile != null) diff --git a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs index 97c00194..ca3a1bee 100644 --- a/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs +++ b/src/ShardingCore/Core/VirtualRoutes/TableRoutes/Abstractions/AbstractVirtualTableRoute.cs @@ -22,11 +22,14 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.Abstractions { private readonly DoOnlyOnce _doOnlyOnce = new DoOnlyOnce(); + public IShardingConfigOption ShardingConfigOption { get; private set; } public virtual void Initialize(EntityMetadata entityMetadata) { if (!_doOnlyOnce.IsUnDo()) throw new ShardingCoreInvalidOperationException("already init"); EntityMetadata = entityMetadata; + ShardingConfigOption = + ShardingContainer.GetRequiredShardingConfigOption(entityMetadata.ShardingDbContextType); } public virtual IPaginationConfiguration CreatePaginationConfiguration() { diff --git a/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs b/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs index 62b63e69..1a2e3d74 100644 --- a/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs +++ b/src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs @@ -43,11 +43,15 @@ namespace ShardingCore.DIExtensions throw new ArgumentException( $"{nameof(shardingCoreBeginOptions.MaxQueryConnectionsLimit)} should greater than and equal 1"); ShardingConfigOption.EnsureCreatedWithOutShardingTable = shardingCoreBeginOptions.EnsureCreatedWithOutShardingTable; - ShardingConfigOption.AutoTrackEntity = shardingCoreBeginOptions.AutoTrackEntity; + //ShardingConfigOption.AutoTrackEntity = shardingCoreBeginOptions.AutoTrackEntity; ShardingConfigOption.CreateShardingTableOnStart = shardingCoreBeginOptions.CreateShardingTableOnStart; ShardingConfigOption.IgnoreCreateTableError = shardingCoreBeginOptions.IgnoreCreateTableError; ShardingConfigOption.MaxQueryConnectionsLimit = shardingCoreBeginOptions.MaxQueryConnectionsLimit; ShardingConfigOption.ConnectionMode = shardingCoreBeginOptions.ConnectionMode; + ShardingConfigOption.ThrowIfQueryRouteNotMatch = shardingCoreBeginOptions.ThrowIfQueryRouteNotMatch; + ShardingConfigOption.EnableTableRouteCompileCache = shardingCoreBeginOptions.EnableTableRouteCompileCache; + ShardingConfigOption.EnableDataSourceRouteCompileCache = shardingCoreBeginOptions.EnableDataSourceRouteCompileCache; + foreach (var entityType in shardingCoreBeginOptions.GetCreateTableEntities()) { ShardingConfigOption.AddEntityTryCreateTable(entityType); @@ -89,13 +93,17 @@ namespace ShardingCore.DIExtensions /// 鏄惁闇瑕佸湪鍚姩鏃跺垱寤哄垎琛 /// public bool? CreateShardingTableOnStart { get; set; } + ///// + ///// 鏄惁鑷姩杩借釜瀹炰綋 + ///// 璀鏈鏌ヨ娑夊強鍒癮1,a2,a3杩欎笁寮犺〃锛屼細鍒涘缓3涓猟bcontext杩涜鏌ヨ锛屽鏋淎utoTrackEntity=false閭d箞閽堝琚垱寤虹殑dbcontext涓嶄細鏈変换浣曞彉鍖栵紝杩樻槸浠ヨ拷韪殑褰㈠紡鏌ヨ + ///// 鍥犱负浼氬悓鏃跺垱寤3涓猟bcontext鎵浠ラ拡瀵硅法琛ㄦ煡璇㈠畬鎴愬悗dbcontext浼氳鍥炴敹锛屼絾鏄煡璇㈣繕鏄寜鍘熷厛鐨勮涓烘煡璇紝鎵浠ュ鏋滀笉鍚敤寤鸿鍦ㄦ煡璇㈢殑鏃跺欎娇鐢╪otracking + ///// 濡傛灉AutoTrackEntity=true锛岄偅涔堣鍒涘缓鐨勪笁涓猟bcontext杩樻槸浠ュ師鍏堢殑琛ㄧ幇琛屼负杩涜鏌ヨ锛屽湪鏌ヨ瀹屾垚鍚庝細鍐嶆鍚勮嚜鍒涘缓瀵瑰簲鐨刣bcontext杩涜瀵硅薄鐨勮拷韪 + ///// + //public bool AutoTrackEntity { get; set; } /// - /// 鏄惁鑷姩杩借釜瀹炰綋 - /// 璀鏈鏌ヨ娑夊強鍒癮1,a2,a3杩欎笁寮犺〃锛屼細鍒涘缓3涓猟bcontext杩涜鏌ヨ锛屽鏋淎utoTrackEntity=false閭d箞閽堝琚垱寤虹殑dbcontext涓嶄細鏈変换浣曞彉鍖栵紝杩樻槸浠ヨ拷韪殑褰㈠紡鏌ヨ - /// 鍥犱负浼氬悓鏃跺垱寤3涓猟bcontext鎵浠ラ拡瀵硅法琛ㄦ煡璇㈠畬鎴愬悗dbcontext浼氳鍥炴敹锛屼絾鏄煡璇㈣繕鏄寜鍘熷厛鐨勮涓烘煡璇紝鎵浠ュ鏋滀笉鍚敤寤鸿鍦ㄦ煡璇㈢殑鏃跺欎娇鐢╪otracking - /// 濡傛灉AutoTrackEntity=true锛岄偅涔堣鍒涘缓鐨勪笁涓猟bcontext杩樻槸浠ュ師鍏堢殑琛ㄧ幇琛屼负杩涜鏌ヨ锛屽湪鏌ヨ瀹屾垚鍚庝細鍐嶆鍚勮嚜鍒涘缓瀵瑰簲鐨刣bcontext杩涜瀵硅薄鐨勮拷韪 + /// 褰撴煡璇㈤亣鍒版病鏈夎矾鐢辫鍛戒腑鏃舵槸鍚︽姏鍑洪敊璇 /// - public bool AutoTrackEntity { get; set; } + public bool ThrowIfQueryRouteNotMatch { get; set; } = true; /// /// 蹇界暐寤鸿〃鏃剁殑閿欒 @@ -103,9 +111,7 @@ namespace ShardingCore.DIExtensions public bool? IgnoreCreateTableError { get; set; } = true; public int MaxQueryConnectionsLimit { get; set; } = Environment.ProcessorCount; public ConnectionModeEnum ConnectionMode { get; set; } = ConnectionModeEnum.SYSTEM_AUTO; - [Obsolete] public bool? EnableTableRouteCompileCache { get; set; } - [Obsolete] public bool? EnableDataSourceRouteCompileCache { get; set; } private readonly ISet _createTableEntities = new HashSet(); diff --git a/src/ShardingCore/Exceptions/ShardingCoreDataSourceQueryRouteNotMatchException.cs b/src/ShardingCore/Exceptions/ShardingCoreDataSourceQueryRouteNotMatchException.cs new file mode 100644 index 00000000..37ce96d4 --- /dev/null +++ b/src/ShardingCore/Exceptions/ShardingCoreDataSourceQueryRouteNotMatchException.cs @@ -0,0 +1,21 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShardingCore.Exceptions +{ + [ExcludeFromCodeCoverage] + public class ShardingCoreDataSourceQueryRouteNotMatchException : ShardingCoreQueryRouteNotMatchException + { + public ShardingCoreDataSourceQueryRouteNotMatchException(string message) : base(message) + { + } + + public ShardingCoreDataSourceQueryRouteNotMatchException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/ShardingCore/Exceptions/ShardingCoreQueryRouteNotMatchException.cs b/src/ShardingCore/Exceptions/ShardingCoreQueryRouteNotMatchException.cs new file mode 100644 index 00000000..a9bbf28f --- /dev/null +++ b/src/ShardingCore/Exceptions/ShardingCoreQueryRouteNotMatchException.cs @@ -0,0 +1,21 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShardingCore.Exceptions +{ + [ExcludeFromCodeCoverage] + public class ShardingCoreQueryRouteNotMatchException : ShardingCoreException + { + public ShardingCoreQueryRouteNotMatchException(string message) : base(message) + { + } + + public ShardingCoreQueryRouteNotMatchException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/ShardingCore/Exceptions/ShardingCoreTableQueryRouteNotMatchException.cs b/src/ShardingCore/Exceptions/ShardingCoreTableQueryRouteNotMatchException.cs new file mode 100644 index 00000000..8c5b7fa7 --- /dev/null +++ b/src/ShardingCore/Exceptions/ShardingCoreTableQueryRouteNotMatchException.cs @@ -0,0 +1,21 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ShardingCore.Exceptions +{ + [ExcludeFromCodeCoverage] + public class ShardingCoreTableQueryRouteNotMatchException : ShardingCoreQueryRouteNotMatchException + { + public ShardingCoreTableQueryRouteNotMatchException(string message) : base(message) + { + } + + public ShardingCoreTableQueryRouteNotMatchException(string message, Exception innerException) : base(message, innerException) + { + } + } +} diff --git a/src/ShardingCore/IShardingConfigOption.cs b/src/ShardingCore/IShardingConfigOption.cs index 43b028e5..c93b89bf 100644 --- a/src/ShardingCore/IShardingConfigOption.cs +++ b/src/ShardingCore/IShardingConfigOption.cs @@ -58,10 +58,10 @@ namespace ShardingCore /// public bool? IgnoreCreateTableError { get; set; } - /// - /// 鑷姩杩借釜瀹炰綋 - /// - public bool AutoTrackEntity { get; set; } + ///// + ///// 鑷姩杩借釜瀹炰綋 + ///// + //public bool AutoTrackEntity { get; set; } /// /// 榛樿鏁版嵁婧愬悕绉 /// @@ -78,18 +78,22 @@ namespace ShardingCore /// 杩炴帴鏁伴檺鍒 /// public ConnectionModeEnum ConnectionMode { get; set; } + /// + /// 褰撴煡璇㈤亣鍒版病鏈夎矾鐢辫鍛戒腑鏃舵槸鍚︽姏鍑洪敊璇 + /// + public bool ThrowIfQueryRouteNotMatch { get; set; } public bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode); public ISet GetParallelTableGroupNodes(); - ///// - ///// 鏄惁鍚敤琛ㄨ矾鐢辩紪璇戠紦瀛 - ///// - //public bool? EnableTableRouteCompileCache { get; set; } - ///// - ///// 鏄惁鍚敤鍒嗗簱璺敱缂栬瘧缂撳瓨 - ///// - //public bool? EnableDataSourceRouteCompileCache { get; set; } + /// + /// 鏄惁鍚敤琛ㄨ矾鐢辩紪璇戠紦瀛 + /// + public bool? EnableTableRouteCompileCache { get; set; } + /// + /// 鏄惁鍚敤鍒嗗簱璺敱缂栬瘧缂撳瓨 + /// + public bool? EnableDataSourceRouteCompileCache { get; set; } } public interface IShardingConfigOption: IShardingConfigOption where TShardingDbContext : DbContext, IShardingDbContext diff --git a/src/ShardingCore/Sharding/MergeEngines/Abstractions/InMemoryMerge/AbstractInMemoryAsyncMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/Abstractions/InMemoryMerge/AbstractInMemoryAsyncMergeEngine.cs index b3aca1be..3c15aec0 100644 --- a/src/ShardingCore/Sharding/MergeEngines/Abstractions/InMemoryMerge/AbstractInMemoryAsyncMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/Abstractions/InMemoryMerge/AbstractInMemoryAsyncMergeEngine.cs @@ -44,8 +44,11 @@ namespace ShardingCore.Sharding.MergeEngines.Abstractions.InMemoryMerge public async Task>> ExecuteAsync(Func> efQuery, CancellationToken cancellationToken = new CancellationToken()) { + var routeQueryResults = _mergeContext.PreperExecute(() => new List>(0)); + if (routeQueryResults != null) + return routeQueryResults; var defaultSqlRouteUnits = GetDefaultSqlRouteUnits(); - var waitExecuteQueue = GetDataSourceGroupAndExecutorGroup>(true,defaultSqlRouteUnits, + var waitExecuteQueue = GetDataSourceGroupAndExecutorGroup>(true, defaultSqlRouteUnits, async sqlExecutorUnit => { var connectionMode = _mergeContext.RealConnectionMode(sqlExecutorUnit.ConnectionMode); diff --git a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/AsyncEnumeratorStreamMergeEngine.cs b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/AsyncEnumeratorStreamMergeEngine.cs index 1a6b4bb7..bfe3722e 100644 --- a/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/AsyncEnumeratorStreamMergeEngine.cs +++ b/src/ShardingCore/Sharding/MergeEngines/EnumeratorStreamMergeEngines/AsyncEnumeratorStreamMergeEngine.cs @@ -4,6 +4,7 @@ using System.Threading; using Microsoft.EntityFrameworkCore; using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Enumerators.TrackerEnumerators; +using ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines.EnumeratorAsync; using ShardingCore.Sharding.ShardingQueryExecutors; /* @@ -29,6 +30,9 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = new CancellationToken()) { cancellationToken.ThrowIfCancellationRequested(); + var emptyQueryEnumerator = _mergeContext.PreperExecute(() => new EmptyQueryEnumerator()); + if (emptyQueryEnumerator != null) + return emptyQueryEnumerator; var asyncEnumerator = EnumeratorStreamMergeEngineFactory.Create(_mergeContext).GetMergeEngine() .GetAsyncEnumerator(cancellationToken); @@ -44,6 +48,9 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines #if EFCORE2 IAsyncEnumerator IAsyncEnumerable.GetEnumerator() { + var emptyQueryEnumerator = _mergeContext.PreperExecute(() => new EmptyQueryEnumerator()); + if (emptyQueryEnumerator != null) + return emptyQueryEnumerator; var asyncEnumerator = ((IAsyncEnumerable)EnumeratorStreamMergeEngineFactory.Create(_mergeContext).GetMergeEngine()) .GetEnumerator(); if (_mergeContext.IsUseShardingTrack(typeof(T))) @@ -57,6 +64,9 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines public IEnumerator GetEnumerator() { + var emptyQueryEnumerator = _mergeContext.PreperExecute(() => new EmptyQueryEnumerator()); + if (emptyQueryEnumerator != null) + return emptyQueryEnumerator; var enumerator = ((IEnumerable)EnumeratorStreamMergeEngineFactory.Create(_mergeContext).GetMergeEngine()) .GetEnumerator(); diff --git a/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs b/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs index fbae0290..cc355045 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/MergeQueryCompilerContext.cs @@ -52,16 +52,17 @@ namespace ShardingCore.Sharding.ShardingExecutors private IEnumerable GetTableRouteResults(IEnumerable tableRouteResults) { - if (_queryCompilerContext.GetQueryEntities().Count > 1) + var routeResults = tableRouteResults as TableRouteResult[] ?? tableRouteResults.ToArray(); + if (_queryCompilerContext.GetQueryEntities().Count > 1&& routeResults.Length>0) { var entityMetadataManager = _queryCompilerContext.GetEntityMetadataManager(); var queryShardingTables = _queryCompilerContext.GetQueryEntities().Where(o => entityMetadataManager.IsShardingTable(o)).ToArray(); if (queryShardingTables.Length > 1 && _parallelTableManager.IsParallelTableQuery(queryShardingTables)) { - return tableRouteResults.Where(o => o.ReplaceTables.Select(p => p.Tail).ToHashSet().Count == 1); + return routeResults.Where(o => o.ReplaceTables.Select(p => p.Tail).ToHashSet().Count == 1); } } - return tableRouteResults; + return routeResults; } public static MergeQueryCompilerContext Create(IQueryCompilerContext queryCompilerContext, QueryCombineResult queryCombineResult, DataSourceRouteResult dataSourceRouteResult,IEnumerable tableRouteResults) @@ -101,12 +102,19 @@ namespace ShardingCore.Sharding.ShardingExecutors { if (!hasQueryCompilerExecutor.HasValue) { - hasQueryCompilerExecutor = !IsMergeQuery(); - if (hasQueryCompilerExecutor.Value) + if (_dataSourceRouteResult.IntersectDataSources.IsEmpty() || _tableRouteResults.IsEmpty()) { - var routeTailFactory = ShardingContainer.GetService(); - var dbContext = GetShardingDbContext().GetDbContext(_dataSourceRouteResult.IntersectDataSources.First(), CurrentQueryReadConnection(), routeTailFactory.Create(_tableRouteResults.First())); - _queryCompilerExecutor = new QueryCompilerExecutor(dbContext, GetQueryExpression()); + hasQueryCompilerExecutor = false; + } + else + { + hasQueryCompilerExecutor = !IsMergeQuery(); + if (hasQueryCompilerExecutor.Value) + { + var routeTailFactory = ShardingContainer.GetService(); + var dbContext = GetShardingDbContext().GetDbContext(_dataSourceRouteResult.IntersectDataSources.First(), CurrentQueryReadConnection(), routeTailFactory.Create(_tableRouteResults.First())); + _queryCompilerExecutor = new QueryCompilerExecutor(dbContext, GetQueryExpression()); + } } } diff --git a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs index 5ddb7e68..2c8a8376 100644 --- a/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs +++ b/src/ShardingCore/Sharding/ShardingExecutors/QueryCompilerContextFactory.cs @@ -45,8 +45,9 @@ namespace ShardingCore.Sharding.ShardingExecutors var queryCombineResult = queryableCombine.Combine(queryCompilerContext); var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable()); var tableRouteResults = tableRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable()); + var routeResults = tableRouteResults as TableRouteResult[] ?? tableRouteResults.ToArray(); var mergeCombineCompilerContext = MergeQueryCompilerContext.Create(queryCompilerContext, queryCombineResult, dataSourceRouteResult, - tableRouteResults); + routeResults); return mergeCombineCompilerContext; } diff --git a/src/ShardingCore/Sharding/StreamMergeContext.cs b/src/ShardingCore/Sharding/StreamMergeContext.cs index 532d9928..835536ec 100644 --- a/src/ShardingCore/Sharding/StreamMergeContext.cs +++ b/src/ShardingCore/Sharding/StreamMergeContext.cs @@ -17,6 +17,8 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ShardingCore.Exceptions; +using ShardingCore.Sharding.StreamMergeEngines; namespace ShardingCore.Sharding @@ -233,7 +235,7 @@ namespace ShardingCore.Sharding /// public bool IsParallelQuery() { - return !_shardingConfigOption.AutoTrackEntity || MergeQueryCompilerContext.IsCrossTable() || MergeQueryCompilerContext.CurrentQueryReadConnection(); + return MergeQueryCompilerContext.IsCrossTable() || MergeQueryCompilerContext.CurrentQueryReadConnection(); } /// @@ -266,6 +268,49 @@ namespace ShardingCore.Sharding { return _shardingComparer; } + + public TResult PreperExecute(Func emptyFunc) + { + + if (IsRouteNotMatch()) + { + if (ThrowIfQueryRouteNotMatch()) + { + if (IsDataSourceRouteNotMatch()) + { + throw new ShardingCoreDataSourceQueryRouteNotMatchException(MergeQueryCompilerContext.GetQueryExpression().ShardingPrint()); + } + else + { + throw new ShardingCoreTableQueryRouteNotMatchException(MergeQueryCompilerContext.GetQueryExpression().ShardingPrint()); + } + } + else + { + return emptyFunc(); + } + } + + return default; + } + /// + /// 鏃犺矾鐢卞尮閰 + /// + /// + private bool IsRouteNotMatch() + { + return DataSourceRouteResult.IntersectDataSources.IsEmpty() || TableRouteResults.IsEmpty(); + } + + private bool IsDataSourceRouteNotMatch() + { + return DataSourceRouteResult.IntersectDataSources.IsEmpty(); + } + + private bool ThrowIfQueryRouteNotMatch() + { + return _shardingConfigOption.ThrowIfQueryRouteNotMatch; + } public void Dispose() { foreach (var dbContext in _parallelDbContexts.Keys) diff --git a/src/ShardingCore/ShardingConfigOption.cs b/src/ShardingCore/ShardingConfigOption.cs index 4cf075fe..73ab54e3 100644 --- a/src/ShardingCore/ShardingConfigOption.cs +++ b/src/ShardingCore/ShardingConfigOption.cs @@ -232,15 +232,21 @@ namespace ShardingCore /// 蹇界暐寤鸿〃鏃剁殑閿欒 /// public bool? IgnoreCreateTableError { get; set; } = true; - /// - /// 鑷姩杩借釜瀹炰綋 - /// - public bool AutoTrackEntity { get; set; } + ///// + ///// 鑷姩杩借釜瀹炰綋 + ///// + //public bool AutoTrackEntity { get; set; } public string DefaultDataSourceName { get; set; } public string DefaultConnectionString { get; set; } public int MaxQueryConnectionsLimit { get; set; } = Environment.ProcessorCount; public ConnectionModeEnum ConnectionMode { get; set; } = ConnectionModeEnum.SYSTEM_AUTO; + /// + /// 褰撴煡璇㈤亣鍒版病鏈夎矾鐢辫鍛戒腑鏃舵槸鍚︽姏鍑洪敊璇 + /// + public bool ThrowIfQueryRouteNotMatch { get; set; } = true; + public bool? EnableTableRouteCompileCache { get; set; } + public bool? EnableDataSourceRouteCompileCache { get; set; } public bool AddParallelTableGroupNode(ParallelTableGroupNode parallelTableGroupNode) diff --git a/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingAutoCreateOperatorVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingAutoCreateOperatorVirtualTableRoute.cs index 5647e330..159cebc6 100644 --- a/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingAutoCreateOperatorVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Abstractions/AbstractShardingAutoCreateOperatorVirtualTableRoute.cs @@ -53,7 +53,7 @@ namespace ShardingCore.VirtualRoutes.Abstractions /// /// public abstract string[] GetCronExpressions(); - public Task ExecuteAsync() + public virtual Task ExecuteAsync() { var virtualTableManager = (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(EntityMetadata.ShardingDbContextType)); var virtualTable = virtualTableManager.GetVirtualTable(typeof(TEntity)); diff --git a/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute.cs index 36ab961c..c6c5cea0 100644 --- a/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute.cs @@ -49,7 +49,7 @@ namespace ShardingCore.VirtualRoutes.Days return $"{time:yyyyMMdd}"; } - public override Expression> GetMainRouteFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyLongVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyLongVirtualTableRoute.cs index 83c3d561..4adaa883 100644 --- a/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyLongVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Days/AbstractSimpleShardingDayKeyLongVirtualTableRoute.cs @@ -41,7 +41,7 @@ namespace ShardingCore.VirtualRoutes.Days return $"{dateTime:yyyyMMdd}"; } - public override Expression> GetMainRouteFilter(long shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(long shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyIntVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyIntVirtualTableRoute.cs index 06a936e7..7ac080b7 100644 --- a/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyIntVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyIntVirtualTableRoute.cs @@ -48,7 +48,7 @@ namespace ShardingCore.VirtualRoutes.Mods return Enumerable.Range(0, Mod).Select(o => o.ToString().PadLeft(TailLength, PaddingChar)).ToList(); } - public override Expression> GetMainRouteFilter(int shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator) { var t = ShardingKeyToTail(shardingKey); diff --git a/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyStringVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyStringVirtualTableRoute.cs index 9defba63..2c514ff9 100644 --- a/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyStringVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Mods/AbstractSimpleShardingModKeyStringVirtualTableRoute.cs @@ -65,7 +65,7 @@ namespace ShardingCore.VirtualRoutes.Mods /// /// /// - public override Expression> GetMainRouteFilter(string shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator) { var t = ShardingKeyToTail(shardingKey); switch (shardingOperator) diff --git a/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute.cs index 7dbd97fc..1e8fb0a0 100644 --- a/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute.cs @@ -39,7 +39,7 @@ namespace ShardingCore.VirtualRoutes.Months return $"{time:yyyyMM}"; } - public override Expression> GetMainRouteFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyLongVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyLongVirtualTableRoute.cs index c4c4699b..b944d46c 100644 --- a/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyLongVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Months/AbstractSimpleShardingMonthKeyLongVirtualTableRoute.cs @@ -41,7 +41,7 @@ namespace ShardingCore.VirtualRoutes.Months var datetime = ShardingCoreHelper.ConvertLongToDateTime(time); return $"{datetime:yyyyMM}"; } - public override Expression> GetMainRouteFilter(long shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(long shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/src/ShardingCore/VirtualRoutes/Weeks/AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Weeks/AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute.cs index 16a29825..57c46b28 100644 --- a/src/ShardingCore/VirtualRoutes/Weeks/AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Weeks/AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute.cs @@ -41,7 +41,7 @@ namespace ShardingCore.VirtualRoutes.Weeks return $"{currentMonday:yyyyMM}{currentMonday:dd}_{currentSunday:dd}"; } - public override Expression> GetMainRouteFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/src/ShardingCore/VirtualRoutes/Weeks/AbstractSimpleShardingWeekKeyLongVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Weeks/AbstractSimpleShardingWeekKeyLongVirtualTableRoute.cs index 0e74846d..d58602df 100644 --- a/src/ShardingCore/VirtualRoutes/Weeks/AbstractSimpleShardingWeekKeyLongVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Weeks/AbstractSimpleShardingWeekKeyLongVirtualTableRoute.cs @@ -50,7 +50,7 @@ namespace ShardingCore.VirtualRoutes.Weeks return $"{currentMonday:yyyyMM}{currentMonday:dd}_{currentSunday:dd}"; } - public override Expression> GetMainRouteFilter(long shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(long shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs index 9be19c45..3c68a5c2 100644 --- a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute.cs @@ -37,7 +37,7 @@ namespace ShardingCore.VirtualRoutes.Years { return $"{time:yyyy}"; } - public override Expression> GetMainRouteFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs index 1cd3242c..8b86a861 100644 --- a/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs +++ b/src/ShardingCore/VirtualRoutes/Years/AbstractSimpleShardingYearKeyLongVirtualTableRoute.cs @@ -60,7 +60,7 @@ namespace ShardingCore.VirtualRoutes.Years /// /// /// 褰撲紶鍏ヨ〃鍚庣紑浣犲憡璇夋鏋惰繖涓悗缂鏄惁闇瑕佽杩斿洖锛屽垎鐗囧瓧娈靛浣曠瓫閫夊嚭鍚庣紑 - public override Expression> GetMainRouteFilter(long shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(long shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/test/ShardingCore.Test/Common/SnowflakeId.cs b/test/ShardingCore.Test/Common/SnowflakeId.cs new file mode 100644 index 00000000..b8d6337d --- /dev/null +++ b/test/ShardingCore.Test/Common/SnowflakeId.cs @@ -0,0 +1,196 @@ +锘縰sing System; +using System.Text; + +namespace ShardingCore.Test.Common +{/// + /// 闆姳ID + /// Twitter_Snowflake + /// SnowFlake鐨勭粨鏋勫涓(姣忛儴鍒嗙敤-鍒嗗紑) + /// 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 + /// 1浣嶆爣璇嗭紝鐢变簬long鍩烘湰绫诲瀷鍦↗ava涓槸甯︾鍙风殑锛屾渶楂樹綅鏄鍙蜂綅锛屾鏁版槸0锛岃礋鏁版槸1锛屾墍浠d涓鑸槸姝f暟锛屾渶楂樹綅鏄0 + /// 41浣嶆椂闂存埅(姣绾)锛屾敞鎰忥紝41浣嶆椂闂存埅涓嶆槸瀛樺偍褰撳墠鏃堕棿鐨勬椂闂存埅锛岃屾槸瀛樺偍鏃堕棿鎴殑宸硷紙褰撳墠鏃堕棿鎴 - 寮濮嬫椂闂存埅)寰楀埌鐨勫硷級锛 + /// 41浣嶇殑鏃堕棿鎴紝鍙互浣跨敤69骞达紝骞碩 = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 + /// 杩欓噷鐨勭殑寮濮嬫椂闂存埅锛屼竴鑸槸鎴戜滑鐨刬d鐢熸垚鍣ㄥ紑濮嬩娇鐢ㄧ殑鏃堕棿锛岀敱鎴戜滑绋嬪簭鏉ユ寚瀹氱殑锛堝涓嬩笅闈㈢▼搴廔dWorker绫荤殑startTime灞炴э級銆 + /// 10浣嶇殑鏁版嵁鏈哄櫒浣嶏紝鍙互閮ㄧ讲鍦1024涓妭鐐癸紝鍖呮嫭5浣峝atacenterId鍜5浣峸orkerId + /// 12浣嶅簭鍒楋紝姣鍐呯殑璁℃暟锛12浣嶇殑璁℃暟椤哄簭鍙锋敮鎸佹瘡涓妭鐐规瘡姣(鍚屼竴鏈哄櫒锛屽悓涓鏃堕棿鎴)浜х敓4096涓狪D搴忓彿 + /// 鎬诲叡鍔犺捣鏉ュ垰濂64浣嶏紝涓轰竴涓狶ong鍨嬨 + /// SnowFlake鐨勪紭鐐规槸锛屾暣浣撲笂鎸夌収鏃堕棿鑷鎺掑簭锛屽苟涓旀暣涓垎甯冨紡绯荤粺鍐呬笉浼氫骇鐢烮D纰版挒(鐢辨暟鎹腑蹇僆D鍜屾満鍣↖D浣滃尯鍒)锛 + /// 骞朵笖鏁堢巼杈冮珮锛岀粡娴嬭瘯锛孲nowFlake鍗曟満姣忕閮借兘澶熶骇鐢熷嚭鏋侀檺4,096,000涓狪D鏉 + /// + public class SnowflakeId + { + + // 寮濮嬫椂闂存埅 (new DateTime(2020, 1, 1).ToUniversalTime() - Jan1st1970).TotalMilliseconds + private const long twepoch = 1577808000000L; + + // 鏈哄櫒id鎵鍗犵殑浣嶆暟 + private const int workerIdBits = 5; + + // 鏁版嵁鏍囪瘑id鎵鍗犵殑浣嶆暟 + private const int datacenterIdBits = 5; + + // 鏀寔鐨勬渶澶ф満鍣╥d锛岀粨鏋滄槸31 (杩欎釜绉讳綅绠楁硶鍙互寰堝揩鐨勮绠楀嚭鍑犱綅浜岃繘鍒舵暟鎵鑳借〃绀虹殑鏈澶у崄杩涘埗鏁) + private const long maxWorkerId = -1L ^ (-1L << workerIdBits); + + // 鏀寔鐨勬渶澶ф暟鎹爣璇唅d锛岀粨鏋滄槸31 + private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + // 搴忓垪鍦╥d涓崰鐨勪綅鏁 + private const int sequenceBits = 12; + + // 鏁版嵁鏍囪瘑id鍚戝乏绉17浣(12+5) + private const int datacenterIdShift = sequenceBits + workerIdBits; + + // 鏈哄櫒ID鍚戝乏绉12浣 + private const int workerIdShift = sequenceBits; + + + // 鏃堕棿鎴悜宸︾Щ22浣(5+5+12) + private const int timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + // 鐢熸垚搴忓垪鐨勬帺鐮侊紝杩欓噷涓4095 (0b111111111111=0xfff=4095) + private const long sequenceMask = -1L ^ (-1L << sequenceBits); + + // 鏁版嵁涓績ID(0~31) + public long datacenterId { get; private set; } + + // 宸ヤ綔鏈哄櫒ID(0~31) + public long workerId { get; private set; } + + // 姣鍐呭簭鍒(0~4095) + public long sequence { get; private set; } + + // 涓婃鐢熸垚ID鐨勬椂闂存埅 + public long lastTimestamp { get; private set; } + + + /// + /// 闆姳ID + /// + /// 鏁版嵁涓績ID + /// 宸ヤ綔鏈哄櫒ID + public SnowflakeId(long datacenterId, long workerId) + { + if (datacenterId > maxDatacenterId || datacenterId < 0) + { + throw new Exception(string.Format("datacenter Id can't be greater than {0} or less than 0", maxDatacenterId)); + } + if (workerId > maxWorkerId || workerId < 0) + { + throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", maxWorkerId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + this.sequence = 0L; + this.lastTimestamp = -1L; + } + + /// + /// 鑾峰緱涓嬩竴涓狪D + /// + /// + public long NextId() + { + lock (this) + { + long timestamp = GetCurrentTimestamp(); + if (timestamp > lastTimestamp) //鏃堕棿鎴虫敼鍙橈紝姣鍐呭簭鍒楅噸缃 + { + sequence = 0L; + } + else if (timestamp == lastTimestamp) //濡傛灉鏄悓涓鏃堕棿鐢熸垚鐨勶紝鍒欒繘琛屾绉掑唴搴忓垪 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) //姣鍐呭簭鍒楁孩鍑 + { + timestamp = GetNextTimestamp(lastTimestamp); //闃诲鍒颁笅涓涓绉,鑾峰緱鏂扮殑鏃堕棿鎴 + } + } + else //褰撳墠鏃堕棿灏忎簬涓婁竴娆D鐢熸垚鐨勬椂闂存埑锛岃瘉鏄庣郴缁熸椂閽熻鍥炴嫧锛屾鏃堕渶瑕佸仛鍥炴嫧澶勭悊 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence > 0) + { + timestamp = lastTimestamp; //鍋滅暀鍦ㄦ渶鍚庝竴娆℃椂闂存埑涓婏紝绛夊緟绯荤粺鏃堕棿杩戒笂鍚庡嵆瀹屽叏搴﹁繃浜嗘椂閽熷洖鎷ㄩ棶棰樸 + } + else //姣鍐呭簭鍒楁孩鍑 + { + timestamp = lastTimestamp + 1; //鐩存帴杩涗綅鍒颁笅涓涓绉 + } + //throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp)); + } + + lastTimestamp = timestamp; //涓婃鐢熸垚ID鐨勬椂闂存埅 + + //绉讳綅骞堕氳繃鎴栬繍绠楁嫾鍒颁竴璧风粍鎴64浣嶇殑ID + var id = ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + return id; + } + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static DateTime AnalyzeIdToDateTime(long Id) + { + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + return time.ToLocalTime(); + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static string AnalyzeId(long Id) + { + StringBuilder sb = new StringBuilder(); + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + sb.Append(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss:fff")); + + var datacenterId = (Id ^ (timestamp << timestampLeftShift)) >> datacenterIdShift; + sb.Append("_" + datacenterId); + + var workerId = (Id ^ ((timestamp << timestampLeftShift) | (datacenterId << datacenterIdShift))) >> workerIdShift; + sb.Append("_" + workerId); + + var sequence = Id & sequenceMask; + sb.Append("_" + sequence); + + return sb.ToString(); + } + + /// + /// 闃诲鍒颁笅涓涓绉掞紝鐩村埌鑾峰緱鏂扮殑鏃堕棿鎴 + /// + /// 涓婃鐢熸垚ID鐨勬椂闂存埅 + /// 褰撳墠鏃堕棿鎴 + private static long GetNextTimestamp(long lastTimestamp) + { + long timestamp = GetCurrentTimestamp(); + while (timestamp <= lastTimestamp) + { + timestamp = GetCurrentTimestamp(); + } + return timestamp; + } + + /// + /// 鑾峰彇褰撳墠鏃堕棿鎴 + /// + /// + private static long GetCurrentTimestamp() + { + return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds; + } + + private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + } +} diff --git a/test/ShardingCore.Test/Domain/Entities/MultiShardingOrder.cs b/test/ShardingCore.Test/Domain/Entities/MultiShardingOrder.cs new file mode 100644 index 00000000..2d2e124d --- /dev/null +++ b/test/ShardingCore.Test/Domain/Entities/MultiShardingOrder.cs @@ -0,0 +1,11 @@ +锘縰sing System; + +namespace ShardingCore.Test.Domain.Entities +{ + public class MultiShardingOrder + { + public long Id { get; set; } + public string Name { get; set; } + public DateTime CreateTime { get; set; } + } +} diff --git a/test/ShardingCore.Test/Domain/Maps/MultiShardingOrderMap.cs b/test/ShardingCore.Test/Domain/Maps/MultiShardingOrderMap.cs new file mode 100644 index 00000000..855d910a --- /dev/null +++ b/test/ShardingCore.Test/Domain/Maps/MultiShardingOrderMap.cs @@ -0,0 +1,22 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using ShardingCore.Test.Domain.Entities; + +namespace ShardingCore.Test.Domain.Maps +{ + public class MultiShardingOrderMap:IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(o => o.Id); + builder.Property(o => o.Id).ValueGeneratedNever(); + builder.Property(o => o.Name).IsRequired().IsUnicode(false).HasMaxLength(50); + builder.ToTable(nameof(MultiShardingOrder)); + } + } +} diff --git a/test/ShardingCore.Test/ShardingDefaultDbContext.cs b/test/ShardingCore.Test/ShardingDefaultDbContext.cs index 6065ffe2..4bc2af1c 100644 --- a/test/ShardingCore.Test/ShardingDefaultDbContext.cs +++ b/test/ShardingCore.Test/ShardingDefaultDbContext.cs @@ -34,6 +34,7 @@ namespace ShardingCore.Test modelBuilder.ApplyConfiguration(new LogYearLongMap()); modelBuilder.ApplyConfiguration(new SysUserModIntMap()); modelBuilder.ApplyConfiguration(new LogDayLongMap()); + modelBuilder.ApplyConfiguration(new MultiShardingOrderMap()); } public IRouteTail RouteTail { get; set; } diff --git a/test/ShardingCore.Test/ShardingTest.cs b/test/ShardingCore.Test/ShardingTest.cs index 4b7835d6..20926558 100644 --- a/test/ShardingCore.Test/ShardingTest.cs +++ b/test/ShardingCore.Test/ShardingTest.cs @@ -86,29 +86,29 @@ namespace ShardingCore.Test var xxxx = "202102"; var queryable1 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202102); var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable2 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= 202102); var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var xxxx1 = 202102; var queryable3 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= xxxx1); var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable4 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202101); var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable5 = _virtualDbContext.Set().Where(o => o.DateOfMonth > 202101); var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable6 = _virtualDbContext.Set().Where(o => o.DateOfMonth == 202101); var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable7 = _virtualDbContext.Set().Where(o => 202101 <= o.DateOfMonth); var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable8 = _virtualDbContext.Set().Where(o => 202101 == o.DateOfMonth); var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2)); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3)); Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4)); @@ -235,6 +235,20 @@ namespace ShardingCore.Test public string Id { get; set; } public string T { get; set; } } + + [Fact] + public async Task TestMultiShardingProperty() + { + + var multiOrder = await _virtualDbContext.Set().Where(o => o.Id == 232398109278351360).FirstOrDefaultAsync(); + Assert.NotNull(multiOrder); + var longs = new[] { 232398109278351360, 255197859283087360 }; + var multiOrders = await _virtualDbContext.Set().Where(o => longs.Contains(o.Id)).ToListAsync(); + Assert.Equal(2, multiOrders.Count); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = await _virtualDbContext.Set().Where(o => o.Id == 250345338962063360 && o.CreateTime < dateTime).FirstOrDefaultAsync(); + Assert.Null(multiOrder404); + } [Fact] public void TestEntityMetadataManager() { diff --git a/test/ShardingCore.Test/ShardingTestSync.cs b/test/ShardingCore.Test/ShardingTestSync.cs index c6e03b09..01b31c98 100644 --- a/test/ShardingCore.Test/ShardingTestSync.cs +++ b/test/ShardingCore.Test/ShardingTestSync.cs @@ -65,29 +65,29 @@ namespace ShardingCore.Test var queryable1 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202102); var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable2 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= 202102); var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var xxxx1 = 202102; var queryable3 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= xxxx1); var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable4 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202101); var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable5 = _virtualDbContext.Set().Where(o => o.DateOfMonth > 202101); var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable6 = _virtualDbContext.Set().Where(o => o.DateOfMonth == 202101); var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable7 = _virtualDbContext.Set().Where(o => 202101 <= o.DateOfMonth); var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable8 = _virtualDbContext.Set().Where(o => 202101 == o.DateOfMonth); var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2)); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3)); Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4)); @@ -190,6 +190,20 @@ namespace ShardingCore.Test public string Id { get; set; } public string T { get; set; } } + + [Fact] + public void TestMultiShardingProperty() + { + + var multiOrder = _virtualDbContext.Set().Where(o => o.Id == 232398109278351360).FirstOrDefault(); + Assert.NotNull(multiOrder); + var longs = new[] { 232398109278351360, 255197859283087360 }; + var multiOrders = _virtualDbContext.Set().Where(o => longs.Contains(o.Id)).ToList(); + Assert.Equal(2, multiOrders.Count); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = _virtualDbContext.Set().Where(o => o.Id == 250345338962063360 && o.CreateTime < dateTime).FirstOrDefault(); + Assert.Null(multiOrder404); + } [Fact] public void TestEntityMetadataManager() { diff --git a/test/ShardingCore.Test/Shardings/LogDayLongVirtualRoute.cs b/test/ShardingCore.Test/Shardings/LogDayLongVirtualRoute.cs index 6f5ab013..76cb9447 100644 --- a/test/ShardingCore.Test/Shardings/LogDayLongVirtualRoute.cs +++ b/test/ShardingCore.Test/Shardings/LogDayLongVirtualRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test.Shardings { public class LogDayLongVirtualRoute:AbstractSimpleShardingDayKeyLongVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; protected override bool EnableHintRoute => true; public override void Configure(EntityMetadataTableBuilder builder) diff --git a/test/ShardingCore.Test/Shardings/LogDayVirtualTableRoute.cs b/test/ShardingCore.Test/Shardings/LogDayVirtualTableRoute.cs index 59e3c4c5..24bf86ea 100644 --- a/test/ShardingCore.Test/Shardings/LogDayVirtualTableRoute.cs +++ b/test/ShardingCore.Test/Shardings/LogDayVirtualTableRoute.cs @@ -10,7 +10,7 @@ namespace ShardingCore.Test.Shardings { public class LogDayVirtualTableRoute:AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; protected override bool EnableHintRoute => true; public override DateTime GetBeginTime() diff --git a/test/ShardingCore.Test/Shardings/LogMonthLongvirtualRoute.cs b/test/ShardingCore.Test/Shardings/LogMonthLongvirtualRoute.cs index c5bb5c6a..7ec6192b 100644 --- a/test/ShardingCore.Test/Shardings/LogMonthLongvirtualRoute.cs +++ b/test/ShardingCore.Test/Shardings/LogMonthLongvirtualRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test.Shardings { public class LogMonthLongvirtualRoute:AbstractSimpleShardingMonthKeyLongVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; protected override bool EnableHintRoute => true; public override bool AutoCreateTableByTime() diff --git a/test/ShardingCore.Test/Shardings/LogWeekDateTimeVirtualTableRoute.cs b/test/ShardingCore.Test/Shardings/LogWeekDateTimeVirtualTableRoute.cs index e8e8e4d8..5cebebca 100644 --- a/test/ShardingCore.Test/Shardings/LogWeekDateTimeVirtualTableRoute.cs +++ b/test/ShardingCore.Test/Shardings/LogWeekDateTimeVirtualTableRoute.cs @@ -7,7 +7,7 @@ namespace ShardingCore.Test.Shardings { public class LogWeekDateTimeVirtualTableRoute:AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; protected override bool EnableHintRoute => true; public override bool AutoCreateTableByTime() diff --git a/test/ShardingCore.Test/Shardings/LogWeekTimeLongVirtualTableRoute.cs b/test/ShardingCore.Test/Shardings/LogWeekTimeLongVirtualTableRoute.cs index eac645a1..485f2fd1 100644 --- a/test/ShardingCore.Test/Shardings/LogWeekTimeLongVirtualTableRoute.cs +++ b/test/ShardingCore.Test/Shardings/LogWeekTimeLongVirtualTableRoute.cs @@ -11,7 +11,7 @@ namespace ShardingCore.Test.Shardings { public class LogWeekTimeLongVirtualTableRoute : AbstractSimpleShardingWeekKeyLongVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; protected override bool EnableHintRoute => true; public override bool AutoCreateTableByTime() diff --git a/test/ShardingCore.Test/Shardings/LogYearDateTimeVirtualRoute.cs b/test/ShardingCore.Test/Shardings/LogYearDateTimeVirtualRoute.cs index 2053fc1c..e8429c2f 100644 --- a/test/ShardingCore.Test/Shardings/LogYearDateTimeVirtualRoute.cs +++ b/test/ShardingCore.Test/Shardings/LogYearDateTimeVirtualRoute.cs @@ -11,7 +11,7 @@ namespace ShardingCore.Test.Shardings { public class LogYearDateTimeVirtualRoute:AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; protected override bool EnableHintRoute => true; public override bool AutoCreateTableByTime() diff --git a/test/ShardingCore.Test/Shardings/LogYearLongVirtualRoute.cs b/test/ShardingCore.Test/Shardings/LogYearLongVirtualRoute.cs index 22ae24d2..1ea94171 100644 --- a/test/ShardingCore.Test/Shardings/LogYearLongVirtualRoute.cs +++ b/test/ShardingCore.Test/Shardings/LogYearLongVirtualRoute.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.PhysicTables; using ShardingCore.Extensions; using ShardingCore.Test.Domain.Entities; using ShardingCore.VirtualRoutes.Years; @@ -12,7 +13,7 @@ namespace ShardingCore.Test.Shardings { public class LogYearLongVirtualRoute:AbstractSimpleShardingYearKeyLongVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; protected override bool EnableHintRoute => true; public override void Configure(EntityMetadataTableBuilder builder) diff --git a/test/ShardingCore.Test/Shardings/MultiShardingOrderVirtualTableRoute.cs b/test/ShardingCore.Test/Shardings/MultiShardingOrderVirtualTableRoute.cs new file mode 100644 index 00000000..387b6c94 --- /dev/null +++ b/test/ShardingCore.Test/Shardings/MultiShardingOrderVirtualTableRoute.cs @@ -0,0 +1,79 @@ +锘縰sing System; +using System.Linq.Expressions; +using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Helpers; +using ShardingCore.Test.Common; +using ShardingCore.Test.Domain.Entities; +using ShardingCore.VirtualRoutes.Months; + +namespace ShardingCore.Test.Shardings +{ + public class MultiShardingOrderVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute + { + public override void Configure(EntityMetadataTableBuilder builder) + { + builder.ShardingProperty(o => o.CreateTime); + builder.ShardingExtraProperty(o => o.Id); + } + + public override Expression> GetExtraRouteFilter(object shardingKey, ShardingOperatorEnum shardingOperator, string shardingPropertyName) + { + switch (shardingPropertyName) + { + case nameof(MultiShardingOrder.Id): return GetIdRouteFilter(shardingKey, shardingOperator); + default: throw new NotImplementedException(shardingPropertyName); + } + } + + private Expression> GetIdRouteFilter(object shardingKey, + ShardingOperatorEnum shardingOperator) + { + //瑙f瀽闆姳id 闇瑕佽冭檻寮傚父鎯呭喌,浼犲叆鐨勫彲鑳戒笉鏄洩鑺眎d閭d箞鍙互闅忔満鏌ヨ涓寮犺〃 + var analyzeIdToDateTime = SnowflakeId.AnalyzeIdToDateTime(Convert.ToInt64(shardingKey)); + //褰撳墠鏃堕棿鐨則ail + var t = TimeFormatToTail(analyzeIdToDateTime); + //鍥犱负鏄寜鏈堝垎琛ㄦ墍浠ヨ幏鍙栦笅涓湀鐨勬椂闂村垽鏂璱d鏄惁鏄湪鐏电晫鐐瑰垱寤虹殑 + var nextMonthFirstDay = ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(10) > nextMonthFirstDay) + { + var nextT = TimeFormatToTail(nextMonthFirstDay); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t||tail== nextT; + } + } + var currentMonthFirstDay = ShardingCoreHelper.GetCurrentMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(-10) < currentMonthFirstDay) + { + //涓婁釜鏈坱ail + var nextT = TimeFormatToTail(analyzeIdToDateTime.AddSeconds(-10)); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t || tail == nextT; + } + } + else + { + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t; + } + } + + return tail => true; + } + + public override bool AutoCreateTableByTime() + { + return true; + } + + public override DateTime GetBeginTime() + { + return new DateTime(2021, 9, 1); + } + } +} diff --git a/test/ShardingCore.Test/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs b/test/ShardingCore.Test/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs index ab9490f7..54e17b7e 100644 --- a/test/ShardingCore.Test/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs +++ b/test/ShardingCore.Test/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs @@ -11,7 +11,7 @@ namespace ShardingCore.Test.Shardings { public class OrderAreaShardingVirtualDataSourceRoute:AbstractShardingOperatorVirtualDataSourceRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; protected override bool EnableHintRoute =>true; private readonly List _dataSources = new List() diff --git a/test/ShardingCore.Test/Shardings/OrderCreateTimeVirtualTableRoute.cs b/test/ShardingCore.Test/Shardings/OrderCreateTimeVirtualTableRoute.cs index 93df8fe9..6341b3bb 100644 --- a/test/ShardingCore.Test/Shardings/OrderCreateTimeVirtualTableRoute.cs +++ b/test/ShardingCore.Test/Shardings/OrderCreateTimeVirtualTableRoute.cs @@ -9,7 +9,7 @@ namespace ShardingCore.Test.Shardings { public class OrderCreateTimeVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override DateTime GetBeginTime() { return new DateTime(2021, 1, 1); diff --git a/test/ShardingCore.Test/Shardings/SysUserModIntVirtualRoute.cs b/test/ShardingCore.Test/Shardings/SysUserModIntVirtualRoute.cs index 2d6fff42..87c6da2d 100644 --- a/test/ShardingCore.Test/Shardings/SysUserModIntVirtualRoute.cs +++ b/test/ShardingCore.Test/Shardings/SysUserModIntVirtualRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test.Shardings public class SysUserModIntVirtualRoute:AbstractSimpleShardingModKeyIntVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public SysUserModIntVirtualRoute() : base(2, 3) { diff --git a/test/ShardingCore.Test/Shardings/SysUserModVirtualTableRoute.cs b/test/ShardingCore.Test/Shardings/SysUserModVirtualTableRoute.cs index 66f46052..80d04314 100644 --- a/test/ShardingCore.Test/Shardings/SysUserModVirtualTableRoute.cs +++ b/test/ShardingCore.Test/Shardings/SysUserModVirtualTableRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test.Shardings public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public SysUserModVirtualTableRoute() : base(2,3) { diff --git a/test/ShardingCore.Test/Shardings/SysUserSalaryVirtualTableRoute.cs b/test/ShardingCore.Test/Shardings/SysUserSalaryVirtualTableRoute.cs index f321b321..47109652 100644 --- a/test/ShardingCore.Test/Shardings/SysUserSalaryVirtualTableRoute.cs +++ b/test/ShardingCore.Test/Shardings/SysUserSalaryVirtualTableRoute.cs @@ -16,7 +16,7 @@ namespace ShardingCore.Test.Shardings */ public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override string ShardingKeyToTail(object shardingKey) { @@ -46,7 +46,7 @@ namespace ShardingCore.Test.Shardings return $"{dateOfMonth:yyyyMM}"; } - public override Expression> GetMainRouteFilter(int shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/test/ShardingCore.Test/Startup.cs b/test/ShardingCore.Test/Startup.cs index 9562016c..b1a1d770 100644 --- a/test/ShardingCore.Test/Startup.cs +++ b/test/ShardingCore.Test/Startup.cs @@ -41,7 +41,7 @@ namespace ShardingCore.Test o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; - o.AutoTrackEntity = true; + o.ThrowIfQueryRouteNotMatch = false; //o.AddParallelTables(typeof(SysUserMod), typeof(SysUserSalary)); }) .AddShardingTransaction((connection, builder) => @@ -72,6 +72,7 @@ namespace ShardingCore.Test op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); + op.AddShardingTableRoute(); }).AddReadWriteSeparation(sp => { return new Dictionary>() @@ -269,6 +270,82 @@ namespace ShardingCore.Test }); begin6 = begin6.AddDays(1); } + var multiShardingOrders = new List(9); + #region 娣诲姞澶氬瓧娈靛垎琛 + + { + var now = new DateTime(2021, 10, 1, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 231765457240207360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 2, 11, 3, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232095129534607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 3, 7, 7, 7); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232398109278351360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 6, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 244811420401807360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 21, 19, 43, 0); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 250345338962063360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 5, 5, 5, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 255197859283087360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 9, 19, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 256860816933007360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 19, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 260394098622607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + #endregion using (var tran = virtualDbContext.Database.BeginTransaction()) { await virtualDbContext.AddRangeAsync(userMods); @@ -282,6 +359,7 @@ namespace ShardingCore.Test await virtualDbContext.AddRangeAsync(logYears); await virtualDbContext.AddRangeAsync(logMonthLongs); await virtualDbContext.AddRangeAsync(logYearkLongs); + await virtualDbContext.AddRangeAsync(multiShardingOrders); await virtualDbContext.SaveChangesAsync(); tran.Commit(); diff --git a/test/ShardingCore.Test2x/Common/SnowflakeId.cs b/test/ShardingCore.Test2x/Common/SnowflakeId.cs new file mode 100644 index 00000000..d4aa9881 --- /dev/null +++ b/test/ShardingCore.Test2x/Common/SnowflakeId.cs @@ -0,0 +1,196 @@ +锘縰sing System; +using System.Text; + +namespace ShardingCore.Test2x.Common +{/// + /// 闆姳ID + /// Twitter_Snowflake + /// SnowFlake鐨勭粨鏋勫涓(姣忛儴鍒嗙敤-鍒嗗紑) + /// 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 + /// 1浣嶆爣璇嗭紝鐢变簬long鍩烘湰绫诲瀷鍦↗ava涓槸甯︾鍙风殑锛屾渶楂樹綅鏄鍙蜂綅锛屾鏁版槸0锛岃礋鏁版槸1锛屾墍浠d涓鑸槸姝f暟锛屾渶楂樹綅鏄0 + /// 41浣嶆椂闂存埅(姣绾)锛屾敞鎰忥紝41浣嶆椂闂存埅涓嶆槸瀛樺偍褰撳墠鏃堕棿鐨勬椂闂存埅锛岃屾槸瀛樺偍鏃堕棿鎴殑宸硷紙褰撳墠鏃堕棿鎴 - 寮濮嬫椂闂存埅)寰楀埌鐨勫硷級锛 + /// 41浣嶇殑鏃堕棿鎴紝鍙互浣跨敤69骞达紝骞碩 = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 + /// 杩欓噷鐨勭殑寮濮嬫椂闂存埅锛屼竴鑸槸鎴戜滑鐨刬d鐢熸垚鍣ㄥ紑濮嬩娇鐢ㄧ殑鏃堕棿锛岀敱鎴戜滑绋嬪簭鏉ユ寚瀹氱殑锛堝涓嬩笅闈㈢▼搴廔dWorker绫荤殑startTime灞炴э級銆 + /// 10浣嶇殑鏁版嵁鏈哄櫒浣嶏紝鍙互閮ㄧ讲鍦1024涓妭鐐癸紝鍖呮嫭5浣峝atacenterId鍜5浣峸orkerId + /// 12浣嶅簭鍒楋紝姣鍐呯殑璁℃暟锛12浣嶇殑璁℃暟椤哄簭鍙锋敮鎸佹瘡涓妭鐐规瘡姣(鍚屼竴鏈哄櫒锛屽悓涓鏃堕棿鎴)浜х敓4096涓狪D搴忓彿 + /// 鎬诲叡鍔犺捣鏉ュ垰濂64浣嶏紝涓轰竴涓狶ong鍨嬨 + /// SnowFlake鐨勪紭鐐规槸锛屾暣浣撲笂鎸夌収鏃堕棿鑷鎺掑簭锛屽苟涓旀暣涓垎甯冨紡绯荤粺鍐呬笉浼氫骇鐢烮D纰版挒(鐢辨暟鎹腑蹇僆D鍜屾満鍣↖D浣滃尯鍒)锛 + /// 骞朵笖鏁堢巼杈冮珮锛岀粡娴嬭瘯锛孲nowFlake鍗曟満姣忕閮借兘澶熶骇鐢熷嚭鏋侀檺4,096,000涓狪D鏉 + /// + public class SnowflakeId + { + + // 寮濮嬫椂闂存埅 (new DateTime(2020, 1, 1).ToUniversalTime() - Jan1st1970).TotalMilliseconds + private const long twepoch = 1577808000000L; + + // 鏈哄櫒id鎵鍗犵殑浣嶆暟 + private const int workerIdBits = 5; + + // 鏁版嵁鏍囪瘑id鎵鍗犵殑浣嶆暟 + private const int datacenterIdBits = 5; + + // 鏀寔鐨勬渶澶ф満鍣╥d锛岀粨鏋滄槸31 (杩欎釜绉讳綅绠楁硶鍙互寰堝揩鐨勮绠楀嚭鍑犱綅浜岃繘鍒舵暟鎵鑳借〃绀虹殑鏈澶у崄杩涘埗鏁) + private const long maxWorkerId = -1L ^ (-1L << workerIdBits); + + // 鏀寔鐨勬渶澶ф暟鎹爣璇唅d锛岀粨鏋滄槸31 + private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + // 搴忓垪鍦╥d涓崰鐨勪綅鏁 + private const int sequenceBits = 12; + + // 鏁版嵁鏍囪瘑id鍚戝乏绉17浣(12+5) + private const int datacenterIdShift = sequenceBits + workerIdBits; + + // 鏈哄櫒ID鍚戝乏绉12浣 + private const int workerIdShift = sequenceBits; + + + // 鏃堕棿鎴悜宸︾Щ22浣(5+5+12) + private const int timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + // 鐢熸垚搴忓垪鐨勬帺鐮侊紝杩欓噷涓4095 (0b111111111111=0xfff=4095) + private const long sequenceMask = -1L ^ (-1L << sequenceBits); + + // 鏁版嵁涓績ID(0~31) + public long datacenterId { get; private set; } + + // 宸ヤ綔鏈哄櫒ID(0~31) + public long workerId { get; private set; } + + // 姣鍐呭簭鍒(0~4095) + public long sequence { get; private set; } + + // 涓婃鐢熸垚ID鐨勬椂闂存埅 + public long lastTimestamp { get; private set; } + + + /// + /// 闆姳ID + /// + /// 鏁版嵁涓績ID + /// 宸ヤ綔鏈哄櫒ID + public SnowflakeId(long datacenterId, long workerId) + { + if (datacenterId > maxDatacenterId || datacenterId < 0) + { + throw new Exception(string.Format("datacenter Id can't be greater than {0} or less than 0", maxDatacenterId)); + } + if (workerId > maxWorkerId || workerId < 0) + { + throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", maxWorkerId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + this.sequence = 0L; + this.lastTimestamp = -1L; + } + + /// + /// 鑾峰緱涓嬩竴涓狪D + /// + /// + public long NextId() + { + lock (this) + { + long timestamp = GetCurrentTimestamp(); + if (timestamp > lastTimestamp) //鏃堕棿鎴虫敼鍙橈紝姣鍐呭簭鍒楅噸缃 + { + sequence = 0L; + } + else if (timestamp == lastTimestamp) //濡傛灉鏄悓涓鏃堕棿鐢熸垚鐨勶紝鍒欒繘琛屾绉掑唴搴忓垪 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) //姣鍐呭簭鍒楁孩鍑 + { + timestamp = GetNextTimestamp(lastTimestamp); //闃诲鍒颁笅涓涓绉,鑾峰緱鏂扮殑鏃堕棿鎴 + } + } + else //褰撳墠鏃堕棿灏忎簬涓婁竴娆D鐢熸垚鐨勬椂闂存埑锛岃瘉鏄庣郴缁熸椂閽熻鍥炴嫧锛屾鏃堕渶瑕佸仛鍥炴嫧澶勭悊 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence > 0) + { + timestamp = lastTimestamp; //鍋滅暀鍦ㄦ渶鍚庝竴娆℃椂闂存埑涓婏紝绛夊緟绯荤粺鏃堕棿杩戒笂鍚庡嵆瀹屽叏搴﹁繃浜嗘椂閽熷洖鎷ㄩ棶棰樸 + } + else //姣鍐呭簭鍒楁孩鍑 + { + timestamp = lastTimestamp + 1; //鐩存帴杩涗綅鍒颁笅涓涓绉 + } + //throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp)); + } + + lastTimestamp = timestamp; //涓婃鐢熸垚ID鐨勬椂闂存埅 + + //绉讳綅骞堕氳繃鎴栬繍绠楁嫾鍒颁竴璧风粍鎴64浣嶇殑ID + var id = ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + return id; + } + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static DateTime AnalyzeIdToDateTime(long Id) + { + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + return time.ToLocalTime(); + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static string AnalyzeId(long Id) + { + StringBuilder sb = new StringBuilder(); + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + sb.Append(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss:fff")); + + var datacenterId = (Id ^ (timestamp << timestampLeftShift)) >> datacenterIdShift; + sb.Append("_" + datacenterId); + + var workerId = (Id ^ ((timestamp << timestampLeftShift) | (datacenterId << datacenterIdShift))) >> workerIdShift; + sb.Append("_" + workerId); + + var sequence = Id & sequenceMask; + sb.Append("_" + sequence); + + return sb.ToString(); + } + + /// + /// 闃诲鍒颁笅涓涓绉掞紝鐩村埌鑾峰緱鏂扮殑鏃堕棿鎴 + /// + /// 涓婃鐢熸垚ID鐨勬椂闂存埅 + /// 褰撳墠鏃堕棿鎴 + private static long GetNextTimestamp(long lastTimestamp) + { + long timestamp = GetCurrentTimestamp(); + while (timestamp <= lastTimestamp) + { + timestamp = GetCurrentTimestamp(); + } + return timestamp; + } + + /// + /// 鑾峰彇褰撳墠鏃堕棿鎴 + /// + /// + private static long GetCurrentTimestamp() + { + return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds; + } + + private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + } +} diff --git a/test/ShardingCore.Test2x/Domain/Entities/MultiShardingOrder.cs b/test/ShardingCore.Test2x/Domain/Entities/MultiShardingOrder.cs new file mode 100644 index 00000000..8d8ce8f9 --- /dev/null +++ b/test/ShardingCore.Test2x/Domain/Entities/MultiShardingOrder.cs @@ -0,0 +1,11 @@ +锘縰sing System; + +namespace ShardingCore.Test2x.Domain.Entities +{ + public class MultiShardingOrder + { + public long Id { get; set; } + public string Name { get; set; } + public DateTime CreateTime { get; set; } + } +} diff --git a/test/ShardingCore.Test2x/Domain/Maps/MultiShardingOrderMap.cs b/test/ShardingCore.Test2x/Domain/Maps/MultiShardingOrderMap.cs new file mode 100644 index 00000000..7f3cdf83 --- /dev/null +++ b/test/ShardingCore.Test2x/Domain/Maps/MultiShardingOrderMap.cs @@ -0,0 +1,22 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using ShardingCore.Test2x.Domain.Entities; + +namespace ShardingCore.Test2x.Domain.Maps +{ + public class MultiShardingOrderMap:IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(o => o.Id); + builder.Property(o => o.Id).ValueGeneratedNever(); + builder.Property(o => o.Name).IsRequired().IsUnicode(false).HasMaxLength(50); + builder.ToTable(nameof(MultiShardingOrder)); + } + } +} diff --git a/test/ShardingCore.Test2x/ShardingDefaultDbContext.cs b/test/ShardingCore.Test2x/ShardingDefaultDbContext.cs index 71ac8900..afca59c5 100644 --- a/test/ShardingCore.Test2x/ShardingDefaultDbContext.cs +++ b/test/ShardingCore.Test2x/ShardingDefaultDbContext.cs @@ -34,6 +34,7 @@ namespace ShardingCore.Test2x modelBuilder.ApplyConfiguration(new LogYearLongMap()); modelBuilder.ApplyConfiguration(new SysUserModIntMap()); modelBuilder.ApplyConfiguration(new LogDayLongMap()); + modelBuilder.ApplyConfiguration(new MultiShardingOrderMap()); } public IRouteTail RouteTail { get; set; } diff --git a/test/ShardingCore.Test2x/ShardingTest.cs b/test/ShardingCore.Test2x/ShardingTest.cs index 36e5a5b2..6a1e7cf0 100644 --- a/test/ShardingCore.Test2x/ShardingTest.cs +++ b/test/ShardingCore.Test2x/ShardingTest.cs @@ -74,29 +74,29 @@ namespace ShardingCore.Test2x var queryable1 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202102); var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable2 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= 202102); var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var xxxx1 = 202102; var queryable3 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= xxxx1); var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable4 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202101); var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable5 = _virtualDbContext.Set().Where(o => o.DateOfMonth > 202101); var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable6 = _virtualDbContext.Set().Where(o => o.DateOfMonth == 202101); var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable7 = _virtualDbContext.Set().Where(o => 202101 <= o.DateOfMonth); var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable8 = _virtualDbContext.Set().Where(o => 202101 == o.DateOfMonth); var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2)); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3)); Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4)); @@ -218,6 +218,20 @@ namespace ShardingCore.Test2x public string Id { get; set; } public string T { get; set; } } + + [Fact] + public async Task TestMultiShardingProperty() + { + + var multiOrder = await _virtualDbContext.Set().Where(o => o.Id == 232398109278351360).FirstOrDefaultAsync(); + Assert.NotNull(multiOrder); + var longs = new[] { 232398109278351360, 255197859283087360 }; + var multiOrders = await _virtualDbContext.Set().Where(o => longs.Contains(o.Id)).ToListAsync(); + Assert.Equal(2, multiOrders.Count); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = await _virtualDbContext.Set().Where(o => o.Id == 250345338962063360 && o.CreateTime < dateTime).FirstOrDefaultAsync(); + Assert.Null(multiOrder404); + } [Fact] public void TestEntityMetadataManager() { diff --git a/test/ShardingCore.Test2x/ShardingTestSync.cs b/test/ShardingCore.Test2x/ShardingTestSync.cs index 59d3b380..fa189dfa 100644 --- a/test/ShardingCore.Test2x/ShardingTestSync.cs +++ b/test/ShardingCore.Test2x/ShardingTestSync.cs @@ -64,29 +64,29 @@ namespace ShardingCore.Test2x var queryable1 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202102); var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable2 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= 202102); var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var xxxx1 = 202102; var queryable3 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= xxxx1); var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable4 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202101); var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable5 = _virtualDbContext.Set().Where(o => o.DateOfMonth > 202101); var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable6 = _virtualDbContext.Set().Where(o => o.DateOfMonth == 202101); var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable7 = _virtualDbContext.Set().Where(o => 202101 <= o.DateOfMonth); var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable8 = _virtualDbContext.Set().Where(o => 202101 == o.DateOfMonth); var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2)); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3)); Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4)); @@ -189,6 +189,19 @@ namespace ShardingCore.Test2x public string T { get; set; } } [Fact] + public void TestMultiShardingProperty() + { + + var multiOrder = _virtualDbContext.Set().Where(o => o.Id == 232398109278351360).FirstOrDefault(); + Assert.NotNull(multiOrder); + var longs = new[] { 232398109278351360, 255197859283087360 }; + var multiOrders = _virtualDbContext.Set().Where(o => longs.Contains(o.Id)).ToList(); + Assert.Equal(2, multiOrders.Count); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = _virtualDbContext.Set().Where(o => o.Id == 250345338962063360 && o.CreateTime < dateTime).FirstOrDefault(); + Assert.Null(multiOrder404); + } + [Fact] public void TestEntityMetadataManager() { var objMetadata0 = _entityMetadataManager.TryGet(typeof(object)); diff --git a/test/ShardingCore.Test2x/Shardings/LogDayLongVirtualRoute.cs b/test/ShardingCore.Test2x/Shardings/LogDayLongVirtualRoute.cs index fb4d7b1f..dc2e72cc 100644 --- a/test/ShardingCore.Test2x/Shardings/LogDayLongVirtualRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/LogDayLongVirtualRoute.cs @@ -10,7 +10,7 @@ namespace ShardingCore.Test2x.Shardings public class LogDayLongVirtualRoute:AbstractSimpleShardingDayKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override void Configure(EntityMetadataTableBuilder builder) { diff --git a/test/ShardingCore.Test2x/Shardings/LogDayVirtualTableRoute.cs b/test/ShardingCore.Test2x/Shardings/LogDayVirtualTableRoute.cs index c7e4d41d..ef1edc8c 100644 --- a/test/ShardingCore.Test2x/Shardings/LogDayVirtualTableRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/LogDayVirtualTableRoute.cs @@ -11,7 +11,7 @@ namespace ShardingCore.Test2x.Shardings public class LogDayVirtualTableRoute:AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override DateTime GetBeginTime() { diff --git a/test/ShardingCore.Test2x/Shardings/LogMonthLongvirtualRoute.cs b/test/ShardingCore.Test2x/Shardings/LogMonthLongvirtualRoute.cs index e9441822..73b3f69a 100644 --- a/test/ShardingCore.Test2x/Shardings/LogMonthLongvirtualRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/LogMonthLongvirtualRoute.cs @@ -8,7 +8,7 @@ namespace ShardingCore.Test2x.Shardings public class LogMonthLongvirtualRoute:AbstractSimpleShardingMonthKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test2x/Shardings/LogWeekDateTimeVirtualTableRoute.cs b/test/ShardingCore.Test2x/Shardings/LogWeekDateTimeVirtualTableRoute.cs index 06c405c5..1c5477eb 100644 --- a/test/ShardingCore.Test2x/Shardings/LogWeekDateTimeVirtualTableRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/LogWeekDateTimeVirtualTableRoute.cs @@ -8,7 +8,7 @@ namespace ShardingCore.Test2x.Shardings public class LogWeekDateTimeVirtualTableRoute:AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test2x/Shardings/LogWeekTimeLongVirtualTableRoute.cs b/test/ShardingCore.Test2x/Shardings/LogWeekTimeLongVirtualTableRoute.cs index 120dea42..4f3a8a75 100644 --- a/test/ShardingCore.Test2x/Shardings/LogWeekTimeLongVirtualTableRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/LogWeekTimeLongVirtualTableRoute.cs @@ -8,7 +8,7 @@ namespace ShardingCore.Test2x.Shardings public class LogWeekTimeLongVirtualTableRoute : AbstractSimpleShardingWeekKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test2x/Shardings/LogYearDateTimeVirtualRoute.cs b/test/ShardingCore.Test2x/Shardings/LogYearDateTimeVirtualRoute.cs index 7e11da91..eae09f82 100644 --- a/test/ShardingCore.Test2x/Shardings/LogYearDateTimeVirtualRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/LogYearDateTimeVirtualRoute.cs @@ -8,7 +8,7 @@ namespace ShardingCore.Test2x.Shardings public class LogYearDateTimeVirtualRoute:AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test2x/Shardings/LogYearLongVirtualRoute.cs b/test/ShardingCore.Test2x/Shardings/LogYearLongVirtualRoute.cs index b1d14221..fbb843a9 100644 --- a/test/ShardingCore.Test2x/Shardings/LogYearLongVirtualRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/LogYearLongVirtualRoute.cs @@ -8,7 +8,7 @@ namespace ShardingCore.Test2x.Shardings public class LogYearLongVirtualRoute:AbstractSimpleShardingYearKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override void Configure(EntityMetadataTableBuilder builder) { diff --git a/test/ShardingCore.Test2x/Shardings/MultiShardingOrderVirtualTableRoute.cs b/test/ShardingCore.Test2x/Shardings/MultiShardingOrderVirtualTableRoute.cs new file mode 100644 index 00000000..a1147d12 --- /dev/null +++ b/test/ShardingCore.Test2x/Shardings/MultiShardingOrderVirtualTableRoute.cs @@ -0,0 +1,79 @@ +锘縰sing System; +using System.Linq.Expressions; +using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Helpers; +using ShardingCore.Test2x.Common; +using ShardingCore.Test2x.Domain.Entities; +using ShardingCore.VirtualRoutes.Months; + +namespace ShardingCore.Test2x.Shardings +{ + public class MultiShardingOrderVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute + { + public override void Configure(EntityMetadataTableBuilder builder) + { + builder.ShardingProperty(o => o.CreateTime); + builder.ShardingExtraProperty(o => o.Id); + } + + public override Expression> GetExtraRouteFilter(object shardingKey, ShardingOperatorEnum shardingOperator, string shardingPropertyName) + { + switch (shardingPropertyName) + { + case nameof(MultiShardingOrder.Id): return GetIdRouteFilter(shardingKey, shardingOperator); + default: throw new NotImplementedException(shardingPropertyName); + } + } + + private Expression> GetIdRouteFilter(object shardingKey, + ShardingOperatorEnum shardingOperator) + { + //瑙f瀽闆姳id 闇瑕佽冭檻寮傚父鎯呭喌,浼犲叆鐨勫彲鑳戒笉鏄洩鑺眎d閭d箞鍙互闅忔満鏌ヨ涓寮犺〃 + var analyzeIdToDateTime = SnowflakeId.AnalyzeIdToDateTime(Convert.ToInt64(shardingKey)); + //褰撳墠鏃堕棿鐨則ail + var t = TimeFormatToTail(analyzeIdToDateTime); + //鍥犱负鏄寜鏈堝垎琛ㄦ墍浠ヨ幏鍙栦笅涓湀鐨勬椂闂村垽鏂璱d鏄惁鏄湪鐏电晫鐐瑰垱寤虹殑 + var nextMonthFirstDay = ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(10) > nextMonthFirstDay) + { + var nextT = TimeFormatToTail(nextMonthFirstDay); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t||tail== nextT; + } + } + var currentMonthFirstDay = ShardingCoreHelper.GetCurrentMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(-10) < currentMonthFirstDay) + { + //涓婁釜鏈坱ail + var nextT = TimeFormatToTail(analyzeIdToDateTime.AddSeconds(-10)); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t || tail == nextT; + } + } + else + { + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t; + } + } + + return tail => true; + } + + public override bool AutoCreateTableByTime() + { + return true; + } + + public override DateTime GetBeginTime() + { + return new DateTime(2021, 9, 1); + } + } +} diff --git a/test/ShardingCore.Test2x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs b/test/ShardingCore.Test2x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs index 7fc3b2c8..e3637b45 100644 --- a/test/ShardingCore.Test2x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test2x.Shardings public class OrderAreaShardingVirtualDataSourceRoute:AbstractShardingOperatorVirtualDataSourceRoute { protected override bool EnableHintRoute =>true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; private readonly List _dataSources = new List() { diff --git a/test/ShardingCore.Test2x/Shardings/OrderCreateTimeVirtualTableRoute.cs b/test/ShardingCore.Test2x/Shardings/OrderCreateTimeVirtualTableRoute.cs index 7f899a55..dbda2750 100644 --- a/test/ShardingCore.Test2x/Shardings/OrderCreateTimeVirtualTableRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/OrderCreateTimeVirtualTableRoute.cs @@ -9,7 +9,7 @@ namespace ShardingCore.Test2x.Shardings { public class OrderCreateTimeVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override DateTime GetBeginTime() { return new DateTime(2021, 1, 1); diff --git a/test/ShardingCore.Test2x/Shardings/SysUserModIntVirtualRoute.cs b/test/ShardingCore.Test2x/Shardings/SysUserModIntVirtualRoute.cs index e3152ec0..e141c2d0 100644 --- a/test/ShardingCore.Test2x/Shardings/SysUserModIntVirtualRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/SysUserModIntVirtualRoute.cs @@ -7,7 +7,7 @@ namespace ShardingCore.Test2x.Shardings public class SysUserModIntVirtualRoute:AbstractSimpleShardingModKeyIntVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public SysUserModIntVirtualRoute() : base(2, 3) { diff --git a/test/ShardingCore.Test2x/Shardings/SysUserModVirtualTableRoute.cs b/test/ShardingCore.Test2x/Shardings/SysUserModVirtualTableRoute.cs index 4bebf866..55a24889 100644 --- a/test/ShardingCore.Test2x/Shardings/SysUserModVirtualTableRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/SysUserModVirtualTableRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test2x.Shardings public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public SysUserModVirtualTableRoute() : base(2,3) { diff --git a/test/ShardingCore.Test2x/Shardings/SysUserSalaryVirtualTableRoute.cs b/test/ShardingCore.Test2x/Shardings/SysUserSalaryVirtualTableRoute.cs index 1baa6551..c49ae093 100644 --- a/test/ShardingCore.Test2x/Shardings/SysUserSalaryVirtualTableRoute.cs +++ b/test/ShardingCore.Test2x/Shardings/SysUserSalaryVirtualTableRoute.cs @@ -16,7 +16,7 @@ namespace ShardingCore.Test2x.Shardings */ public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override string ShardingKeyToTail(object shardingKey) { var time = Convert.ToInt32(shardingKey); @@ -45,7 +45,7 @@ namespace ShardingCore.Test2x.Shardings return $"{dateOfMonth:yyyyMM}"; } - public override Expression> GetMainRouteFilter(int shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/test/ShardingCore.Test2x/Startup.cs b/test/ShardingCore.Test2x/Startup.cs index 641f392f..547e71dd 100644 --- a/test/ShardingCore.Test2x/Startup.cs +++ b/test/ShardingCore.Test2x/Startup.cs @@ -40,7 +40,7 @@ namespace ShardingCore.Test2x { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; - o.AutoTrackEntity = true; + o.ThrowIfQueryRouteNotMatch = false; }) .AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger)) @@ -70,6 +70,7 @@ namespace ShardingCore.Test2x op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); + op.AddShardingTableRoute(); }).AddReadWriteSeparation(sp => { return new Dictionary>() @@ -267,6 +268,82 @@ namespace ShardingCore.Test2x }); begin6 = begin6.AddDays(1); } + var multiShardingOrders = new List(9); + #region 娣诲姞澶氬瓧娈靛垎琛 + + { + var now = new DateTime(2021, 10, 1, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 231765457240207360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 2, 11, 3, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232095129534607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 3, 7, 7, 7); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232398109278351360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 6, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 244811420401807360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 21, 19, 43, 0); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 250345338962063360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 5, 5, 5, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 255197859283087360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 9, 19, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 256860816933007360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 19, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 260394098622607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + #endregion using (var tran = virtualDbContext.Database.BeginTransaction()) { await virtualDbContext.AddRangeAsync(userMods); @@ -280,6 +357,7 @@ namespace ShardingCore.Test2x await virtualDbContext.AddRangeAsync(logYears); await virtualDbContext.AddRangeAsync(logMonthLongs); await virtualDbContext.AddRangeAsync(logYearkLongs); + await virtualDbContext.AddRangeAsync(multiShardingOrders); await virtualDbContext.SaveChangesAsync(); tran.Commit(); diff --git a/test/ShardingCore.Test3x/Common/SnowflakeId.cs b/test/ShardingCore.Test3x/Common/SnowflakeId.cs new file mode 100644 index 00000000..93743534 --- /dev/null +++ b/test/ShardingCore.Test3x/Common/SnowflakeId.cs @@ -0,0 +1,196 @@ +锘縰sing System; +using System.Text; + +namespace ShardingCore.Test3x.Common +{/// + /// 闆姳ID + /// Twitter_Snowflake + /// SnowFlake鐨勭粨鏋勫涓(姣忛儴鍒嗙敤-鍒嗗紑) + /// 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 + /// 1浣嶆爣璇嗭紝鐢变簬long鍩烘湰绫诲瀷鍦↗ava涓槸甯︾鍙风殑锛屾渶楂樹綅鏄鍙蜂綅锛屾鏁版槸0锛岃礋鏁版槸1锛屾墍浠d涓鑸槸姝f暟锛屾渶楂樹綅鏄0 + /// 41浣嶆椂闂存埅(姣绾)锛屾敞鎰忥紝41浣嶆椂闂存埅涓嶆槸瀛樺偍褰撳墠鏃堕棿鐨勬椂闂存埅锛岃屾槸瀛樺偍鏃堕棿鎴殑宸硷紙褰撳墠鏃堕棿鎴 - 寮濮嬫椂闂存埅)寰楀埌鐨勫硷級锛 + /// 41浣嶇殑鏃堕棿鎴紝鍙互浣跨敤69骞达紝骞碩 = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 + /// 杩欓噷鐨勭殑寮濮嬫椂闂存埅锛屼竴鑸槸鎴戜滑鐨刬d鐢熸垚鍣ㄥ紑濮嬩娇鐢ㄧ殑鏃堕棿锛岀敱鎴戜滑绋嬪簭鏉ユ寚瀹氱殑锛堝涓嬩笅闈㈢▼搴廔dWorker绫荤殑startTime灞炴э級銆 + /// 10浣嶇殑鏁版嵁鏈哄櫒浣嶏紝鍙互閮ㄧ讲鍦1024涓妭鐐癸紝鍖呮嫭5浣峝atacenterId鍜5浣峸orkerId + /// 12浣嶅簭鍒楋紝姣鍐呯殑璁℃暟锛12浣嶇殑璁℃暟椤哄簭鍙锋敮鎸佹瘡涓妭鐐规瘡姣(鍚屼竴鏈哄櫒锛屽悓涓鏃堕棿鎴)浜х敓4096涓狪D搴忓彿 + /// 鎬诲叡鍔犺捣鏉ュ垰濂64浣嶏紝涓轰竴涓狶ong鍨嬨 + /// SnowFlake鐨勪紭鐐规槸锛屾暣浣撲笂鎸夌収鏃堕棿鑷鎺掑簭锛屽苟涓旀暣涓垎甯冨紡绯荤粺鍐呬笉浼氫骇鐢烮D纰版挒(鐢辨暟鎹腑蹇僆D鍜屾満鍣↖D浣滃尯鍒)锛 + /// 骞朵笖鏁堢巼杈冮珮锛岀粡娴嬭瘯锛孲nowFlake鍗曟満姣忕閮借兘澶熶骇鐢熷嚭鏋侀檺4,096,000涓狪D鏉 + /// + public class SnowflakeId + { + + // 寮濮嬫椂闂存埅 (new DateTime(2020, 1, 1).ToUniversalTime() - Jan1st1970).TotalMilliseconds + private const long twepoch = 1577808000000L; + + // 鏈哄櫒id鎵鍗犵殑浣嶆暟 + private const int workerIdBits = 5; + + // 鏁版嵁鏍囪瘑id鎵鍗犵殑浣嶆暟 + private const int datacenterIdBits = 5; + + // 鏀寔鐨勬渶澶ф満鍣╥d锛岀粨鏋滄槸31 (杩欎釜绉讳綅绠楁硶鍙互寰堝揩鐨勮绠楀嚭鍑犱綅浜岃繘鍒舵暟鎵鑳借〃绀虹殑鏈澶у崄杩涘埗鏁) + private const long maxWorkerId = -1L ^ (-1L << workerIdBits); + + // 鏀寔鐨勬渶澶ф暟鎹爣璇唅d锛岀粨鏋滄槸31 + private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + // 搴忓垪鍦╥d涓崰鐨勪綅鏁 + private const int sequenceBits = 12; + + // 鏁版嵁鏍囪瘑id鍚戝乏绉17浣(12+5) + private const int datacenterIdShift = sequenceBits + workerIdBits; + + // 鏈哄櫒ID鍚戝乏绉12浣 + private const int workerIdShift = sequenceBits; + + + // 鏃堕棿鎴悜宸︾Щ22浣(5+5+12) + private const int timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + // 鐢熸垚搴忓垪鐨勬帺鐮侊紝杩欓噷涓4095 (0b111111111111=0xfff=4095) + private const long sequenceMask = -1L ^ (-1L << sequenceBits); + + // 鏁版嵁涓績ID(0~31) + public long datacenterId { get; private set; } + + // 宸ヤ綔鏈哄櫒ID(0~31) + public long workerId { get; private set; } + + // 姣鍐呭簭鍒(0~4095) + public long sequence { get; private set; } + + // 涓婃鐢熸垚ID鐨勬椂闂存埅 + public long lastTimestamp { get; private set; } + + + /// + /// 闆姳ID + /// + /// 鏁版嵁涓績ID + /// 宸ヤ綔鏈哄櫒ID + public SnowflakeId(long datacenterId, long workerId) + { + if (datacenterId > maxDatacenterId || datacenterId < 0) + { + throw new Exception(string.Format("datacenter Id can't be greater than {0} or less than 0", maxDatacenterId)); + } + if (workerId > maxWorkerId || workerId < 0) + { + throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", maxWorkerId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + this.sequence = 0L; + this.lastTimestamp = -1L; + } + + /// + /// 鑾峰緱涓嬩竴涓狪D + /// + /// + public long NextId() + { + lock (this) + { + long timestamp = GetCurrentTimestamp(); + if (timestamp > lastTimestamp) //鏃堕棿鎴虫敼鍙橈紝姣鍐呭簭鍒楅噸缃 + { + sequence = 0L; + } + else if (timestamp == lastTimestamp) //濡傛灉鏄悓涓鏃堕棿鐢熸垚鐨勶紝鍒欒繘琛屾绉掑唴搴忓垪 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) //姣鍐呭簭鍒楁孩鍑 + { + timestamp = GetNextTimestamp(lastTimestamp); //闃诲鍒颁笅涓涓绉,鑾峰緱鏂扮殑鏃堕棿鎴 + } + } + else //褰撳墠鏃堕棿灏忎簬涓婁竴娆D鐢熸垚鐨勬椂闂存埑锛岃瘉鏄庣郴缁熸椂閽熻鍥炴嫧锛屾鏃堕渶瑕佸仛鍥炴嫧澶勭悊 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence > 0) + { + timestamp = lastTimestamp; //鍋滅暀鍦ㄦ渶鍚庝竴娆℃椂闂存埑涓婏紝绛夊緟绯荤粺鏃堕棿杩戒笂鍚庡嵆瀹屽叏搴﹁繃浜嗘椂閽熷洖鎷ㄩ棶棰樸 + } + else //姣鍐呭簭鍒楁孩鍑 + { + timestamp = lastTimestamp + 1; //鐩存帴杩涗綅鍒颁笅涓涓绉 + } + //throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp)); + } + + lastTimestamp = timestamp; //涓婃鐢熸垚ID鐨勬椂闂存埅 + + //绉讳綅骞堕氳繃鎴栬繍绠楁嫾鍒颁竴璧风粍鎴64浣嶇殑ID + var id = ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + return id; + } + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static DateTime AnalyzeIdToDateTime(long Id) + { + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + return time.ToLocalTime(); + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static string AnalyzeId(long Id) + { + StringBuilder sb = new StringBuilder(); + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + sb.Append(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss:fff")); + + var datacenterId = (Id ^ (timestamp << timestampLeftShift)) >> datacenterIdShift; + sb.Append("_" + datacenterId); + + var workerId = (Id ^ ((timestamp << timestampLeftShift) | (datacenterId << datacenterIdShift))) >> workerIdShift; + sb.Append("_" + workerId); + + var sequence = Id & sequenceMask; + sb.Append("_" + sequence); + + return sb.ToString(); + } + + /// + /// 闃诲鍒颁笅涓涓绉掞紝鐩村埌鑾峰緱鏂扮殑鏃堕棿鎴 + /// + /// 涓婃鐢熸垚ID鐨勬椂闂存埅 + /// 褰撳墠鏃堕棿鎴 + private static long GetNextTimestamp(long lastTimestamp) + { + long timestamp = GetCurrentTimestamp(); + while (timestamp <= lastTimestamp) + { + timestamp = GetCurrentTimestamp(); + } + return timestamp; + } + + /// + /// 鑾峰彇褰撳墠鏃堕棿鎴 + /// + /// + private static long GetCurrentTimestamp() + { + return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds; + } + + private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + } +} diff --git a/test/ShardingCore.Test3x/Domain/Entities/MultiShardingOrder.cs b/test/ShardingCore.Test3x/Domain/Entities/MultiShardingOrder.cs new file mode 100644 index 00000000..fc2db5fa --- /dev/null +++ b/test/ShardingCore.Test3x/Domain/Entities/MultiShardingOrder.cs @@ -0,0 +1,11 @@ +锘縰sing System; + +namespace ShardingCore.Test3x.Domain.Entities +{ + public class MultiShardingOrder + { + public long Id { get; set; } + public string Name { get; set; } + public DateTime CreateTime { get; set; } + } +} diff --git a/test/ShardingCore.Test3x/Domain/Maps/MultiShardingOrderMap.cs b/test/ShardingCore.Test3x/Domain/Maps/MultiShardingOrderMap.cs new file mode 100644 index 00000000..b6928b10 --- /dev/null +++ b/test/ShardingCore.Test3x/Domain/Maps/MultiShardingOrderMap.cs @@ -0,0 +1,17 @@ +锘縰sing Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using ShardingCore.Test3x.Domain.Entities; + +namespace ShardingCore.Test3x.Domain.Maps +{ + public class MultiShardingOrderMap:IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(o => o.Id); + builder.Property(o => o.Id).ValueGeneratedNever(); + builder.Property(o => o.Name).IsRequired().IsUnicode(false).HasMaxLength(50); + builder.ToTable(nameof(MultiShardingOrder)); + } + } +} diff --git a/test/ShardingCore.Test3x/ShardingDefaultDbContext.cs b/test/ShardingCore.Test3x/ShardingDefaultDbContext.cs index 7de74a4c..1007394f 100644 --- a/test/ShardingCore.Test3x/ShardingDefaultDbContext.cs +++ b/test/ShardingCore.Test3x/ShardingDefaultDbContext.cs @@ -34,6 +34,7 @@ namespace ShardingCore.Test3x modelBuilder.ApplyConfiguration(new LogYearLongMap()); modelBuilder.ApplyConfiguration(new SysUserModIntMap()); modelBuilder.ApplyConfiguration(new LogDayLongMap()); + modelBuilder.ApplyConfiguration(new MultiShardingOrderMap()); } public IRouteTail RouteTail { get; set; } diff --git a/test/ShardingCore.Test3x/ShardingTest.cs b/test/ShardingCore.Test3x/ShardingTest.cs index 1986aceb..15fc29e1 100644 --- a/test/ShardingCore.Test3x/ShardingTest.cs +++ b/test/ShardingCore.Test3x/ShardingTest.cs @@ -74,29 +74,29 @@ namespace ShardingCore.Test3x var queryable1 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202102); var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable2 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= 202102); var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var xxxx1 = 202102; var queryable3 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= xxxx1); var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable4 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202101); var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable5 = _virtualDbContext.Set().Where(o => o.DateOfMonth > 202101); var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable6 = _virtualDbContext.Set().Where(o => o.DateOfMonth == 202101); var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable7 = _virtualDbContext.Set().Where(o => 202101 <= o.DateOfMonth); var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable8 = _virtualDbContext.Set().Where(o => 202101 == o.DateOfMonth); var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2)); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3)); Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4)); @@ -217,6 +217,20 @@ namespace ShardingCore.Test3x public string Id { get; set; } public string T { get; set; } } + + [Fact] + public async Task TestMultiShardingProperty() + { + + var multiOrder = await _virtualDbContext.Set().Where(o => o.Id == 232398109278351360).FirstOrDefaultAsync(); + Assert.NotNull(multiOrder); + var longs = new[] { 232398109278351360, 255197859283087360 }; + var multiOrders = await _virtualDbContext.Set().Where(o => longs.Contains(o.Id)).ToListAsync(); + Assert.Equal(2, multiOrders.Count); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = await _virtualDbContext.Set().Where(o => o.Id == 250345338962063360 && o.CreateTime < dateTime).FirstOrDefaultAsync(); + Assert.Null(multiOrder404); + } [Fact] public void TestEntityMetadataManager() { diff --git a/test/ShardingCore.Test3x/ShardingTestSync.cs b/test/ShardingCore.Test3x/ShardingTestSync.cs index be6a6481..b6817192 100644 --- a/test/ShardingCore.Test3x/ShardingTestSync.cs +++ b/test/ShardingCore.Test3x/ShardingTestSync.cs @@ -65,29 +65,29 @@ namespace ShardingCore.Test3x var queryable1 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202102); var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable2 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= 202102); var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var xxxx1 = 202102; var queryable3 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= xxxx1); var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable4 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202101); var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable5 = _virtualDbContext.Set().Where(o => o.DateOfMonth > 202101); var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable6 = _virtualDbContext.Set().Where(o => o.DateOfMonth == 202101); var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable7 = _virtualDbContext.Set().Where(o => 202101 <= o.DateOfMonth); var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable8 = _virtualDbContext.Set().Where(o => 202101 == o.DateOfMonth); var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2)); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3)); Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4)); @@ -191,6 +191,19 @@ namespace ShardingCore.Test3x public string T { get; set; } } [Fact] + public void TestMultiShardingProperty() + { + + var multiOrder = _virtualDbContext.Set().Where(o => o.Id == 232398109278351360).FirstOrDefault(); + Assert.NotNull(multiOrder); + var longs = new[] { 232398109278351360, 255197859283087360 }; + var multiOrders = _virtualDbContext.Set().Where(o => longs.Contains(o.Id)).ToList(); + Assert.Equal(2, multiOrders.Count); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = _virtualDbContext.Set().Where(o => o.Id == 250345338962063360 && o.CreateTime < dateTime).FirstOrDefault(); + Assert.Null(multiOrder404); + } + [Fact] public void TestEntityMetadataManager() { var objMetadata0 = _entityMetadataManager.TryGet(typeof(object)); diff --git a/test/ShardingCore.Test3x/Shardings/LogDayLongVirtualRoute.cs b/test/ShardingCore.Test3x/Shardings/LogDayLongVirtualRoute.cs index 8a6beb40..a8e90ff0 100644 --- a/test/ShardingCore.Test3x/Shardings/LogDayLongVirtualRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/LogDayLongVirtualRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test3x.Shardings public class LogDayLongVirtualRoute:AbstractSimpleShardingDayKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override void Configure(EntityMetadataTableBuilder builder) { diff --git a/test/ShardingCore.Test3x/Shardings/LogDayVirtualTableRoute.cs b/test/ShardingCore.Test3x/Shardings/LogDayVirtualTableRoute.cs index 120b5cad..3e46d9aa 100644 --- a/test/ShardingCore.Test3x/Shardings/LogDayVirtualTableRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/LogDayVirtualTableRoute.cs @@ -11,7 +11,7 @@ namespace ShardingCore.Test3x.Shardings public class LogDayVirtualTableRoute:AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override DateTime GetBeginTime() { diff --git a/test/ShardingCore.Test3x/Shardings/LogMonthLongvirtualRoute.cs b/test/ShardingCore.Test3x/Shardings/LogMonthLongvirtualRoute.cs index 78d12df1..49b09560 100644 --- a/test/ShardingCore.Test3x/Shardings/LogMonthLongvirtualRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/LogMonthLongvirtualRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test3x.Shardings public class LogMonthLongvirtualRoute:AbstractSimpleShardingMonthKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test3x/Shardings/LogWeekDateTimeVirtualTableRoute.cs b/test/ShardingCore.Test3x/Shardings/LogWeekDateTimeVirtualTableRoute.cs index 13a4993e..576199f5 100644 --- a/test/ShardingCore.Test3x/Shardings/LogWeekDateTimeVirtualTableRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/LogWeekDateTimeVirtualTableRoute.cs @@ -8,7 +8,7 @@ namespace ShardingCore.Test3x.Shardings public class LogWeekDateTimeVirtualTableRoute:AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test3x/Shardings/LogWeekTimeLongVirtualTableRoute.cs b/test/ShardingCore.Test3x/Shardings/LogWeekTimeLongVirtualTableRoute.cs index 1ae46d98..f0185062 100644 --- a/test/ShardingCore.Test3x/Shardings/LogWeekTimeLongVirtualTableRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/LogWeekTimeLongVirtualTableRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test3x.Shardings public class LogWeekTimeLongVirtualTableRoute : AbstractSimpleShardingWeekKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test3x/Shardings/LogYearDateTimeVirtualRoute.cs b/test/ShardingCore.Test3x/Shardings/LogYearDateTimeVirtualRoute.cs index 07f1aa71..57fc8530 100644 --- a/test/ShardingCore.Test3x/Shardings/LogYearDateTimeVirtualRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/LogYearDateTimeVirtualRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test3x.Shardings public class LogYearDateTimeVirtualRoute:AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test3x/Shardings/LogYearLongVirtualRoute.cs b/test/ShardingCore.Test3x/Shardings/LogYearLongVirtualRoute.cs index dca01f7c..3f37a985 100644 --- a/test/ShardingCore.Test3x/Shardings/LogYearLongVirtualRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/LogYearLongVirtualRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test3x.Shardings public class LogYearLongVirtualRoute:AbstractSimpleShardingYearKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override void Configure(EntityMetadataTableBuilder builder) { diff --git a/test/ShardingCore.Test3x/Shardings/MultiShardingOrderVirtualTableRoute.cs b/test/ShardingCore.Test3x/Shardings/MultiShardingOrderVirtualTableRoute.cs new file mode 100644 index 00000000..a6f89636 --- /dev/null +++ b/test/ShardingCore.Test3x/Shardings/MultiShardingOrderVirtualTableRoute.cs @@ -0,0 +1,79 @@ +锘縰sing System; +using System.Linq.Expressions; +using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Helpers; +using ShardingCore.Test3x.Common; +using ShardingCore.Test3x.Domain.Entities; +using ShardingCore.VirtualRoutes.Months; + +namespace ShardingCore.Test3x.Shardings +{ + public class MultiShardingOrderVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute + { + public override void Configure(EntityMetadataTableBuilder builder) + { + builder.ShardingProperty(o => o.CreateTime); + builder.ShardingExtraProperty(o => o.Id); + } + + public override Expression> GetExtraRouteFilter(object shardingKey, ShardingOperatorEnum shardingOperator, string shardingPropertyName) + { + switch (shardingPropertyName) + { + case nameof(MultiShardingOrder.Id): return GetIdRouteFilter(shardingKey, shardingOperator); + default: throw new NotImplementedException(shardingPropertyName); + } + } + + private Expression> GetIdRouteFilter(object shardingKey, + ShardingOperatorEnum shardingOperator) + { + //瑙f瀽闆姳id 闇瑕佽冭檻寮傚父鎯呭喌,浼犲叆鐨勫彲鑳戒笉鏄洩鑺眎d閭d箞鍙互闅忔満鏌ヨ涓寮犺〃 + var analyzeIdToDateTime = SnowflakeId.AnalyzeIdToDateTime(Convert.ToInt64(shardingKey)); + //褰撳墠鏃堕棿鐨則ail + var t = TimeFormatToTail(analyzeIdToDateTime); + //鍥犱负鏄寜鏈堝垎琛ㄦ墍浠ヨ幏鍙栦笅涓湀鐨勬椂闂村垽鏂璱d鏄惁鏄湪鐏电晫鐐瑰垱寤虹殑 + var nextMonthFirstDay = ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(10) > nextMonthFirstDay) + { + var nextT = TimeFormatToTail(nextMonthFirstDay); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t||tail== nextT; + } + } + var currentMonthFirstDay = ShardingCoreHelper.GetCurrentMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(-10) < currentMonthFirstDay) + { + //涓婁釜鏈坱ail + var nextT = TimeFormatToTail(analyzeIdToDateTime.AddSeconds(-10)); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t || tail == nextT; + } + } + else + { + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t; + } + } + + return tail => true; + } + + public override bool AutoCreateTableByTime() + { + return true; + } + + public override DateTime GetBeginTime() + { + return new DateTime(2021, 9, 1); + } + } +} diff --git a/test/ShardingCore.Test3x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs b/test/ShardingCore.Test3x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs index c67c914d..398ecda2 100644 --- a/test/ShardingCore.Test3x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test3x.Shardings public class OrderAreaShardingVirtualDataSourceRoute:AbstractShardingOperatorVirtualDataSourceRoute { protected override bool EnableHintRoute =>true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; private readonly List _dataSources = new List() { diff --git a/test/ShardingCore.Test3x/Shardings/OrderCreateTimeVirtualTableRoute.cs b/test/ShardingCore.Test3x/Shardings/OrderCreateTimeVirtualTableRoute.cs index 4fbb8596..8eab1249 100644 --- a/test/ShardingCore.Test3x/Shardings/OrderCreateTimeVirtualTableRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/OrderCreateTimeVirtualTableRoute.cs @@ -9,7 +9,7 @@ namespace ShardingCore.Test3x.Shardings { public class OrderCreateTimeVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override DateTime GetBeginTime() { return new DateTime(2021, 1, 1); diff --git a/test/ShardingCore.Test3x/Shardings/SysUserModIntVirtualRoute.cs b/test/ShardingCore.Test3x/Shardings/SysUserModIntVirtualRoute.cs index 4a3fe400..492611a7 100644 --- a/test/ShardingCore.Test3x/Shardings/SysUserModIntVirtualRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/SysUserModIntVirtualRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test3x.Shardings { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public SysUserModIntVirtualRoute() : base(2, 3) { } diff --git a/test/ShardingCore.Test3x/Shardings/SysUserModVirtualTableRoute.cs b/test/ShardingCore.Test3x/Shardings/SysUserModVirtualTableRoute.cs index e66d802e..226a1500 100644 --- a/test/ShardingCore.Test3x/Shardings/SysUserModVirtualTableRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/SysUserModVirtualTableRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test3x.Shardings public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public SysUserModVirtualTableRoute() : base(2,3) { diff --git a/test/ShardingCore.Test3x/Shardings/SysUserSalaryVirtualTableRoute.cs b/test/ShardingCore.Test3x/Shardings/SysUserSalaryVirtualTableRoute.cs index a06cfcf3..838f7939 100644 --- a/test/ShardingCore.Test3x/Shardings/SysUserSalaryVirtualTableRoute.cs +++ b/test/ShardingCore.Test3x/Shardings/SysUserSalaryVirtualTableRoute.cs @@ -17,7 +17,7 @@ namespace ShardingCore.Test3x.Shardings public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override string ShardingKeyToTail(object shardingKey) { var time = Convert.ToInt32(shardingKey); @@ -46,7 +46,7 @@ namespace ShardingCore.Test3x.Shardings return $"{dateOfMonth:yyyyMM}"; } - public override Expression> GetMainRouteFilter(int shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/test/ShardingCore.Test3x/Startup.cs b/test/ShardingCore.Test3x/Startup.cs index d35e9aca..dcf2ebc6 100644 --- a/test/ShardingCore.Test3x/Startup.cs +++ b/test/ShardingCore.Test3x/Startup.cs @@ -40,7 +40,7 @@ namespace ShardingCore.Test3x { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; - o.AutoTrackEntity = true; + o.ThrowIfQueryRouteNotMatch = false; }) .AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger)) @@ -70,6 +70,7 @@ namespace ShardingCore.Test3x op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); + op.AddShardingTableRoute(); }).AddReadWriteSeparation(sp => { return new Dictionary>() @@ -267,6 +268,82 @@ namespace ShardingCore.Test3x }); begin6 = begin6.AddDays(1); } + var multiShardingOrders = new List(9); + #region 娣诲姞澶氬瓧娈靛垎琛 + + { + var now = new DateTime(2021, 10, 1, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 231765457240207360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 2, 11, 3, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232095129534607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 3, 7, 7, 7); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232398109278351360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 6, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 244811420401807360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 21, 19, 43, 0); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 250345338962063360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 5, 5, 5, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 255197859283087360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 9, 19, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 256860816933007360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 19, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 260394098622607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + #endregion using (var tran = virtualDbContext.Database.BeginTransaction()) { await virtualDbContext.AddRangeAsync(userMods); @@ -280,6 +357,7 @@ namespace ShardingCore.Test3x await virtualDbContext.AddRangeAsync(logYears); await virtualDbContext.AddRangeAsync(logMonthLongs); await virtualDbContext.AddRangeAsync(logYearkLongs); + await virtualDbContext.AddRangeAsync(multiShardingOrders); await virtualDbContext.SaveChangesAsync(); tran.Commit(); diff --git a/test/ShardingCore.Test5x/Common/SnowflakeId.cs b/test/ShardingCore.Test5x/Common/SnowflakeId.cs new file mode 100644 index 00000000..be3d14ab --- /dev/null +++ b/test/ShardingCore.Test5x/Common/SnowflakeId.cs @@ -0,0 +1,196 @@ +锘縰sing System; +using System.Text; + +namespace ShardingCore.Test5x.Common +{/// + /// 闆姳ID + /// Twitter_Snowflake + /// SnowFlake鐨勭粨鏋勫涓(姣忛儴鍒嗙敤-鍒嗗紑) + /// 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 + /// 1浣嶆爣璇嗭紝鐢变簬long鍩烘湰绫诲瀷鍦↗ava涓槸甯︾鍙风殑锛屾渶楂樹綅鏄鍙蜂綅锛屾鏁版槸0锛岃礋鏁版槸1锛屾墍浠d涓鑸槸姝f暟锛屾渶楂樹綅鏄0 + /// 41浣嶆椂闂存埅(姣绾)锛屾敞鎰忥紝41浣嶆椂闂存埅涓嶆槸瀛樺偍褰撳墠鏃堕棿鐨勬椂闂存埅锛岃屾槸瀛樺偍鏃堕棿鎴殑宸硷紙褰撳墠鏃堕棿鎴 - 寮濮嬫椂闂存埅)寰楀埌鐨勫硷級锛 + /// 41浣嶇殑鏃堕棿鎴紝鍙互浣跨敤69骞达紝骞碩 = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 + /// 杩欓噷鐨勭殑寮濮嬫椂闂存埅锛屼竴鑸槸鎴戜滑鐨刬d鐢熸垚鍣ㄥ紑濮嬩娇鐢ㄧ殑鏃堕棿锛岀敱鎴戜滑绋嬪簭鏉ユ寚瀹氱殑锛堝涓嬩笅闈㈢▼搴廔dWorker绫荤殑startTime灞炴э級銆 + /// 10浣嶇殑鏁版嵁鏈哄櫒浣嶏紝鍙互閮ㄧ讲鍦1024涓妭鐐癸紝鍖呮嫭5浣峝atacenterId鍜5浣峸orkerId + /// 12浣嶅簭鍒楋紝姣鍐呯殑璁℃暟锛12浣嶇殑璁℃暟椤哄簭鍙锋敮鎸佹瘡涓妭鐐规瘡姣(鍚屼竴鏈哄櫒锛屽悓涓鏃堕棿鎴)浜х敓4096涓狪D搴忓彿 + /// 鎬诲叡鍔犺捣鏉ュ垰濂64浣嶏紝涓轰竴涓狶ong鍨嬨 + /// SnowFlake鐨勪紭鐐规槸锛屾暣浣撲笂鎸夌収鏃堕棿鑷鎺掑簭锛屽苟涓旀暣涓垎甯冨紡绯荤粺鍐呬笉浼氫骇鐢烮D纰版挒(鐢辨暟鎹腑蹇僆D鍜屾満鍣↖D浣滃尯鍒)锛 + /// 骞朵笖鏁堢巼杈冮珮锛岀粡娴嬭瘯锛孲nowFlake鍗曟満姣忕閮借兘澶熶骇鐢熷嚭鏋侀檺4,096,000涓狪D鏉 + /// + public class SnowflakeId + { + + // 寮濮嬫椂闂存埅 (new DateTime(2020, 1, 1).ToUniversalTime() - Jan1st1970).TotalMilliseconds + private const long twepoch = 1577808000000L; + + // 鏈哄櫒id鎵鍗犵殑浣嶆暟 + private const int workerIdBits = 5; + + // 鏁版嵁鏍囪瘑id鎵鍗犵殑浣嶆暟 + private const int datacenterIdBits = 5; + + // 鏀寔鐨勬渶澶ф満鍣╥d锛岀粨鏋滄槸31 (杩欎釜绉讳綅绠楁硶鍙互寰堝揩鐨勮绠楀嚭鍑犱綅浜岃繘鍒舵暟鎵鑳借〃绀虹殑鏈澶у崄杩涘埗鏁) + private const long maxWorkerId = -1L ^ (-1L << workerIdBits); + + // 鏀寔鐨勬渶澶ф暟鎹爣璇唅d锛岀粨鏋滄槸31 + private const long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); + + // 搴忓垪鍦╥d涓崰鐨勪綅鏁 + private const int sequenceBits = 12; + + // 鏁版嵁鏍囪瘑id鍚戝乏绉17浣(12+5) + private const int datacenterIdShift = sequenceBits + workerIdBits; + + // 鏈哄櫒ID鍚戝乏绉12浣 + private const int workerIdShift = sequenceBits; + + + // 鏃堕棿鎴悜宸︾Щ22浣(5+5+12) + private const int timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; + + // 鐢熸垚搴忓垪鐨勬帺鐮侊紝杩欓噷涓4095 (0b111111111111=0xfff=4095) + private const long sequenceMask = -1L ^ (-1L << sequenceBits); + + // 鏁版嵁涓績ID(0~31) + public long datacenterId { get; private set; } + + // 宸ヤ綔鏈哄櫒ID(0~31) + public long workerId { get; private set; } + + // 姣鍐呭簭鍒(0~4095) + public long sequence { get; private set; } + + // 涓婃鐢熸垚ID鐨勬椂闂存埅 + public long lastTimestamp { get; private set; } + + + /// + /// 闆姳ID + /// + /// 鏁版嵁涓績ID + /// 宸ヤ綔鏈哄櫒ID + public SnowflakeId(long datacenterId, long workerId) + { + if (datacenterId > maxDatacenterId || datacenterId < 0) + { + throw new Exception(string.Format("datacenter Id can't be greater than {0} or less than 0", maxDatacenterId)); + } + if (workerId > maxWorkerId || workerId < 0) + { + throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", maxWorkerId)); + } + this.workerId = workerId; + this.datacenterId = datacenterId; + this.sequence = 0L; + this.lastTimestamp = -1L; + } + + /// + /// 鑾峰緱涓嬩竴涓狪D + /// + /// + public long NextId() + { + lock (this) + { + long timestamp = GetCurrentTimestamp(); + if (timestamp > lastTimestamp) //鏃堕棿鎴虫敼鍙橈紝姣鍐呭簭鍒楅噸缃 + { + sequence = 0L; + } + else if (timestamp == lastTimestamp) //濡傛灉鏄悓涓鏃堕棿鐢熸垚鐨勶紝鍒欒繘琛屾绉掑唴搴忓垪 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) //姣鍐呭簭鍒楁孩鍑 + { + timestamp = GetNextTimestamp(lastTimestamp); //闃诲鍒颁笅涓涓绉,鑾峰緱鏂扮殑鏃堕棿鎴 + } + } + else //褰撳墠鏃堕棿灏忎簬涓婁竴娆D鐢熸垚鐨勬椂闂存埑锛岃瘉鏄庣郴缁熸椂閽熻鍥炴嫧锛屾鏃堕渶瑕佸仛鍥炴嫧澶勭悊 + { + sequence = (sequence + 1) & sequenceMask; + if (sequence > 0) + { + timestamp = lastTimestamp; //鍋滅暀鍦ㄦ渶鍚庝竴娆℃椂闂存埑涓婏紝绛夊緟绯荤粺鏃堕棿杩戒笂鍚庡嵆瀹屽叏搴﹁繃浜嗘椂閽熷洖鎷ㄩ棶棰樸 + } + else //姣鍐呭簭鍒楁孩鍑 + { + timestamp = lastTimestamp + 1; //鐩存帴杩涗綅鍒颁笅涓涓绉 + } + //throw new Exception(string.Format("Clock moved backwards. Refusing to generate id for {0} milliseconds", lastTimestamp - timestamp)); + } + + lastTimestamp = timestamp; //涓婃鐢熸垚ID鐨勬椂闂存埅 + + //绉讳綅骞堕氳繃鎴栬繍绠楁嫾鍒颁竴璧风粍鎴64浣嶇殑ID + var id = ((timestamp - twepoch) << timestampLeftShift) + | (datacenterId << datacenterIdShift) + | (workerId << workerIdShift) + | sequence; + return id; + } + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static DateTime AnalyzeIdToDateTime(long Id) + { + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + return time.ToLocalTime(); + } + + /// + /// 瑙f瀽闆姳ID + /// + /// + public static string AnalyzeId(long Id) + { + StringBuilder sb = new StringBuilder(); + + var timestamp = (Id >> timestampLeftShift); + var time = Jan1st1970.AddMilliseconds(timestamp + twepoch); + sb.Append(time.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss:fff")); + + var datacenterId = (Id ^ (timestamp << timestampLeftShift)) >> datacenterIdShift; + sb.Append("_" + datacenterId); + + var workerId = (Id ^ ((timestamp << timestampLeftShift) | (datacenterId << datacenterIdShift))) >> workerIdShift; + sb.Append("_" + workerId); + + var sequence = Id & sequenceMask; + sb.Append("_" + sequence); + + return sb.ToString(); + } + + /// + /// 闃诲鍒颁笅涓涓绉掞紝鐩村埌鑾峰緱鏂扮殑鏃堕棿鎴 + /// + /// 涓婃鐢熸垚ID鐨勬椂闂存埅 + /// 褰撳墠鏃堕棿鎴 + private static long GetNextTimestamp(long lastTimestamp) + { + long timestamp = GetCurrentTimestamp(); + while (timestamp <= lastTimestamp) + { + timestamp = GetCurrentTimestamp(); + } + return timestamp; + } + + /// + /// 鑾峰彇褰撳墠鏃堕棿鎴 + /// + /// + private static long GetCurrentTimestamp() + { + return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds; + } + + private static readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + } +} diff --git a/test/ShardingCore.Test5x/Domain/Entities/MultiShardingOrder.cs b/test/ShardingCore.Test5x/Domain/Entities/MultiShardingOrder.cs new file mode 100644 index 00000000..74fef636 --- /dev/null +++ b/test/ShardingCore.Test5x/Domain/Entities/MultiShardingOrder.cs @@ -0,0 +1,11 @@ +锘縰sing System; + +namespace ShardingCore.Test5x.Domain.Entities +{ + public class MultiShardingOrder + { + public long Id { get; set; } + public string Name { get; set; } + public DateTime CreateTime { get; set; } + } +} diff --git a/test/ShardingCore.Test5x/Domain/Maps/MultiShardingOrderMap.cs b/test/ShardingCore.Test5x/Domain/Maps/MultiShardingOrderMap.cs new file mode 100644 index 00000000..98602fec --- /dev/null +++ b/test/ShardingCore.Test5x/Domain/Maps/MultiShardingOrderMap.cs @@ -0,0 +1,17 @@ +锘縰sing Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using ShardingCore.Test5x.Domain.Entities; + +namespace ShardingCore.Test5x.Domain.Maps +{ + public class MultiShardingOrderMap:IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(o => o.Id); + builder.Property(o => o.Id).ValueGeneratedNever(); + builder.Property(o => o.Name).IsRequired().IsUnicode(false).HasMaxLength(50); + builder.ToTable(nameof(MultiShardingOrder)); + } + } +} diff --git a/test/ShardingCore.Test5x/ShardingDefaultDbContext.cs b/test/ShardingCore.Test5x/ShardingDefaultDbContext.cs index 9b863722..919deb1c 100644 --- a/test/ShardingCore.Test5x/ShardingDefaultDbContext.cs +++ b/test/ShardingCore.Test5x/ShardingDefaultDbContext.cs @@ -34,6 +34,7 @@ namespace ShardingCore.Test5x modelBuilder.ApplyConfiguration(new LogYearLongMap()); modelBuilder.ApplyConfiguration(new SysUserModIntMap()); modelBuilder.ApplyConfiguration(new LogDayLongMap()); + modelBuilder.ApplyConfiguration(new MultiShardingOrderMap()); } public IRouteTail RouteTail { get; set; } diff --git a/test/ShardingCore.Test5x/ShardingTest.cs b/test/ShardingCore.Test5x/ShardingTest.cs index a379bb58..70348ec3 100644 --- a/test/ShardingCore.Test5x/ShardingTest.cs +++ b/test/ShardingCore.Test5x/ShardingTest.cs @@ -74,29 +74,29 @@ namespace ShardingCore.Test5x var queryable1 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202102); var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata, - (i, op, propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable2 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= 202102); var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var xxxx1 = 202102; var queryable3 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= xxxx1); var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable4 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202101); var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable5 = _virtualDbContext.Set().Where(o => o.DateOfMonth > 202101); var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable6 = _virtualDbContext.Set().Where(o => o.DateOfMonth == 202101); var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable7 = _virtualDbContext.Set().Where(o => 202101 <= o.DateOfMonth); var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable8 = _virtualDbContext.Set().Where(o => 202101 == o.DateOfMonth); var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2)); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3)); Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4)); @@ -217,6 +217,20 @@ namespace ShardingCore.Test5x public string Id { get; set; } public string T { get; set; } } + + [Fact] + public async Task TestMultiShardingProperty() + { + + var multiOrder = await _virtualDbContext.Set().Where(o => o.Id == 232398109278351360).FirstOrDefaultAsync(); + Assert.NotNull(multiOrder); + var longs = new[] { 232398109278351360, 255197859283087360 }; + var multiOrders = await _virtualDbContext.Set().Where(o => longs.Contains(o.Id)).ToListAsync(); + Assert.Equal(2, multiOrders.Count); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = await _virtualDbContext.Set().Where(o => o.Id == 250345338962063360 && o.CreateTime < dateTime).FirstOrDefaultAsync(); + Assert.Null(multiOrder404); + } [Fact] public void TestEntityMetadataManager() { diff --git a/test/ShardingCore.Test5x/ShardingTestSync.cs b/test/ShardingCore.Test5x/ShardingTestSync.cs index 62633b98..4e3e73cb 100644 --- a/test/ShardingCore.Test5x/ShardingTestSync.cs +++ b/test/ShardingCore.Test5x/ShardingTestSync.cs @@ -66,29 +66,29 @@ namespace ShardingCore.Test5x var queryable1 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202102); var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable2 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= 202102); var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var xxxx1 = 202102; var queryable3 = _virtualDbContext.Set().Where(ox => ox.DateOfMonth >= xxxx1); var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable4 = _virtualDbContext.Set().Where(o => o.DateOfMonth >= 202101); var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable5 = _virtualDbContext.Set().Where(o => o.DateOfMonth > 202101); var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable6 = _virtualDbContext.Set().Where(o => o.DateOfMonth == 202101); var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable7 = _virtualDbContext.Set().Where(o => 202101 <= o.DateOfMonth); var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); var queryable8 = _virtualDbContext.Set().Where(o => 202101 == o.DateOfMonth); var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata, - (i, op,propertyName) => virtualTableRoute.GetRouteToFilter(i, op,propertyName), true); + (i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2)); Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3)); Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4)); @@ -191,6 +191,19 @@ namespace ShardingCore.Test5x public string T { get; set; } } [Fact] + public void TestMultiShardingProperty() + { + + var multiOrder = _virtualDbContext.Set().Where(o => o.Id == 232398109278351360).FirstOrDefault(); + Assert.NotNull(multiOrder); + var longs = new[] { 232398109278351360, 255197859283087360 }; + var multiOrders = _virtualDbContext.Set().Where(o => longs.Contains(o.Id)).ToList(); + Assert.Equal(2, multiOrders.Count); + var dateTime = new DateTime(2021, 11, 1); + var multiOrder404 = _virtualDbContext.Set().Where(o => o.Id == 250345338962063360 && o.CreateTime < dateTime).FirstOrDefault(); + Assert.Null(multiOrder404); + } + [Fact] public void TestEntityMetadataManager() { var objMetadata0 = _entityMetadataManager.TryGet(typeof(object)); diff --git a/test/ShardingCore.Test5x/Shardings/LogDayLongVirtualRoute.cs b/test/ShardingCore.Test5x/Shardings/LogDayLongVirtualRoute.cs index 211a51b8..d1aaa42d 100644 --- a/test/ShardingCore.Test5x/Shardings/LogDayLongVirtualRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/LogDayLongVirtualRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test5x.Shardings public class LogDayLongVirtualRoute:AbstractSimpleShardingDayKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override void Configure(EntityMetadataTableBuilder builder) { diff --git a/test/ShardingCore.Test5x/Shardings/LogDayVirtualTableRoute.cs b/test/ShardingCore.Test5x/Shardings/LogDayVirtualTableRoute.cs index 66828c73..53a9fa4d 100644 --- a/test/ShardingCore.Test5x/Shardings/LogDayVirtualTableRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/LogDayVirtualTableRoute.cs @@ -11,7 +11,7 @@ namespace ShardingCore.Test5x.Shardings public class LogDayVirtualTableRoute:AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override DateTime GetBeginTime() { diff --git a/test/ShardingCore.Test5x/Shardings/LogMonthLongvirtualRoute.cs b/test/ShardingCore.Test5x/Shardings/LogMonthLongvirtualRoute.cs index d96caad6..b1e33884 100644 --- a/test/ShardingCore.Test5x/Shardings/LogMonthLongvirtualRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/LogMonthLongvirtualRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test5x.Shardings public class LogMonthLongvirtualRoute:AbstractSimpleShardingMonthKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test5x/Shardings/LogWeekDateTimeVirtualTableRoute.cs b/test/ShardingCore.Test5x/Shardings/LogWeekDateTimeVirtualTableRoute.cs index 2c904ad3..08482181 100644 --- a/test/ShardingCore.Test5x/Shardings/LogWeekDateTimeVirtualTableRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/LogWeekDateTimeVirtualTableRoute.cs @@ -8,7 +8,7 @@ namespace ShardingCore.Test5x.Shardings public class LogWeekDateTimeVirtualTableRoute:AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test5x/Shardings/LogWeekTimeLongVirtualTableRoute.cs b/test/ShardingCore.Test5x/Shardings/LogWeekTimeLongVirtualTableRoute.cs index 516dc1b0..91b3c93c 100644 --- a/test/ShardingCore.Test5x/Shardings/LogWeekTimeLongVirtualTableRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/LogWeekTimeLongVirtualTableRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test5x.Shardings public class LogWeekTimeLongVirtualTableRoute : AbstractSimpleShardingWeekKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test5x/Shardings/LogYearDateTimeVirtualRoute.cs b/test/ShardingCore.Test5x/Shardings/LogYearDateTimeVirtualRoute.cs index 82f5b39e..5b89d1aa 100644 --- a/test/ShardingCore.Test5x/Shardings/LogYearDateTimeVirtualRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/LogYearDateTimeVirtualRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test5x.Shardings public class LogYearDateTimeVirtualRoute:AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override bool AutoCreateTableByTime() { diff --git a/test/ShardingCore.Test5x/Shardings/LogYearLongVirtualRoute.cs b/test/ShardingCore.Test5x/Shardings/LogYearLongVirtualRoute.cs index dc1e4ce9..2fd15bdb 100644 --- a/test/ShardingCore.Test5x/Shardings/LogYearLongVirtualRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/LogYearLongVirtualRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test5x.Shardings public class LogYearLongVirtualRoute:AbstractSimpleShardingYearKeyLongVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override void Configure(EntityMetadataTableBuilder builder) { diff --git a/test/ShardingCore.Test5x/Shardings/MultiShardingOrderVirtualTableRoute.cs b/test/ShardingCore.Test5x/Shardings/MultiShardingOrderVirtualTableRoute.cs new file mode 100644 index 00000000..49cbcc2a --- /dev/null +++ b/test/ShardingCore.Test5x/Shardings/MultiShardingOrderVirtualTableRoute.cs @@ -0,0 +1,79 @@ +锘縰sing System; +using System.Linq.Expressions; +using ShardingCore.Core.EntityMetadatas; +using ShardingCore.Core.VirtualRoutes; +using ShardingCore.Helpers; +using ShardingCore.Test5x.Common; +using ShardingCore.Test5x.Domain.Entities; +using ShardingCore.VirtualRoutes.Months; + +namespace ShardingCore.Test5x.Shardings +{ + public class MultiShardingOrderVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute + { + public override void Configure(EntityMetadataTableBuilder builder) + { + builder.ShardingProperty(o => o.CreateTime); + builder.ShardingExtraProperty(o => o.Id); + } + + public override Expression> GetExtraRouteFilter(object shardingKey, ShardingOperatorEnum shardingOperator, string shardingPropertyName) + { + switch (shardingPropertyName) + { + case nameof(MultiShardingOrder.Id): return GetIdRouteFilter(shardingKey, shardingOperator); + default: throw new NotImplementedException(shardingPropertyName); + } + } + + private Expression> GetIdRouteFilter(object shardingKey, + ShardingOperatorEnum shardingOperator) + { + //瑙f瀽闆姳id 闇瑕佽冭檻寮傚父鎯呭喌,浼犲叆鐨勫彲鑳戒笉鏄洩鑺眎d閭d箞鍙互闅忔満鏌ヨ涓寮犺〃 + var analyzeIdToDateTime = SnowflakeId.AnalyzeIdToDateTime(Convert.ToInt64(shardingKey)); + //褰撳墠鏃堕棿鐨則ail + var t = TimeFormatToTail(analyzeIdToDateTime); + //鍥犱负鏄寜鏈堝垎琛ㄦ墍浠ヨ幏鍙栦笅涓湀鐨勬椂闂村垽鏂璱d鏄惁鏄湪鐏电晫鐐瑰垱寤虹殑 + var nextMonthFirstDay = ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(10) > nextMonthFirstDay) + { + var nextT = TimeFormatToTail(nextMonthFirstDay); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t||tail== nextT; + } + } + var currentMonthFirstDay = ShardingCoreHelper.GetCurrentMonthFirstDay(DateTime.Now); + if (analyzeIdToDateTime.AddSeconds(-10) < currentMonthFirstDay) + { + //涓婁釜鏈坱ail + var nextT = TimeFormatToTail(analyzeIdToDateTime.AddSeconds(-10)); + + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t || tail == nextT; + } + } + else + { + if (shardingOperator == ShardingOperatorEnum.Equal) + { + return tail => tail == t; + } + } + + return tail => true; + } + + public override bool AutoCreateTableByTime() + { + return true; + } + + public override DateTime GetBeginTime() + { + return new DateTime(2021, 9, 1); + } + } +} diff --git a/test/ShardingCore.Test5x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs b/test/ShardingCore.Test5x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs index 9a11be0c..10c64b0e 100644 --- a/test/ShardingCore.Test5x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/OrderAreaShardingVirtualDataSourceRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test5x.Shardings public class OrderAreaShardingVirtualDataSourceRoute:AbstractShardingOperatorVirtualDataSourceRoute { protected override bool EnableHintRoute =>true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; private readonly List _dataSources = new List() { diff --git a/test/ShardingCore.Test5x/Shardings/OrderCreateTimeVirtualTableRoute.cs b/test/ShardingCore.Test5x/Shardings/OrderCreateTimeVirtualTableRoute.cs index c2273329..c7fb3d5b 100644 --- a/test/ShardingCore.Test5x/Shardings/OrderCreateTimeVirtualTableRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/OrderCreateTimeVirtualTableRoute.cs @@ -9,7 +9,7 @@ namespace ShardingCore.Test5x.Shardings { public class OrderCreateTimeVirtualTableRoute:AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override DateTime GetBeginTime() { return new DateTime(2021, 1, 1); diff --git a/test/ShardingCore.Test5x/Shardings/SysUserModIntVirtualRoute.cs b/test/ShardingCore.Test5x/Shardings/SysUserModIntVirtualRoute.cs index 2cc29384..c27c89c5 100644 --- a/test/ShardingCore.Test5x/Shardings/SysUserModIntVirtualRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/SysUserModIntVirtualRoute.cs @@ -12,7 +12,7 @@ namespace ShardingCore.Test5x.Shardings public class SysUserModIntVirtualRoute:AbstractSimpleShardingModKeyIntVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public SysUserModIntVirtualRoute() : base(2, 3) { diff --git a/test/ShardingCore.Test5x/Shardings/SysUserModVirtualTableRoute.cs b/test/ShardingCore.Test5x/Shardings/SysUserModVirtualTableRoute.cs index 2d94bbee..7250ed5a 100644 --- a/test/ShardingCore.Test5x/Shardings/SysUserModVirtualTableRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/SysUserModVirtualTableRoute.cs @@ -13,7 +13,7 @@ namespace ShardingCore.Test5x.Shardings public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute { protected override bool EnableHintRoute => true; - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public SysUserModVirtualTableRoute() : base(2,3) { diff --git a/test/ShardingCore.Test5x/Shardings/SysUserSalaryVirtualTableRoute.cs b/test/ShardingCore.Test5x/Shardings/SysUserSalaryVirtualTableRoute.cs index 05122bf6..d5ed7b27 100644 --- a/test/ShardingCore.Test5x/Shardings/SysUserSalaryVirtualTableRoute.cs +++ b/test/ShardingCore.Test5x/Shardings/SysUserSalaryVirtualTableRoute.cs @@ -16,7 +16,7 @@ namespace ShardingCore.Test5x.Shardings */ public class SysUserSalaryVirtualTableRoute:AbstractShardingOperatorVirtualTableRoute { - public override bool EnableRouteParseCompileCache => true; + public override bool? EnableRouteParseCompileCache => true; public override string ShardingKeyToTail(object shardingKey) { var time = Convert.ToInt32(shardingKey); @@ -45,7 +45,7 @@ namespace ShardingCore.Test5x.Shardings return $"{dateOfMonth:yyyyMM}"; } - public override Expression> GetMainRouteFilter(int shardingKey, ShardingOperatorEnum shardingOperator) + public override Expression> GetRouteToFilter(int shardingKey, ShardingOperatorEnum shardingOperator) { var t = TimeFormatToTail(shardingKey); switch (shardingOperator) diff --git a/test/ShardingCore.Test5x/Startup.cs b/test/ShardingCore.Test5x/Startup.cs index 71adec7a..73e9cf98 100644 --- a/test/ShardingCore.Test5x/Startup.cs +++ b/test/ShardingCore.Test5x/Startup.cs @@ -40,7 +40,7 @@ namespace ShardingCore.Test5x { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; - o.AutoTrackEntity = true; + o.ThrowIfQueryRouteNotMatch = false; }) .AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger)) @@ -70,6 +70,7 @@ namespace ShardingCore.Test5x op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); + op.AddShardingTableRoute(); }).AddReadWriteSeparation(sp => { return new Dictionary>() @@ -267,6 +268,83 @@ namespace ShardingCore.Test5x }); begin6 = begin6.AddDays(1); } + + var multiShardingOrders = new List(9); + #region 娣诲姞澶氬瓧娈靛垎琛 + + { + var now = new DateTime(2021, 10, 1, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 231765457240207360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 2, 11, 3, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232095129534607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 10, 3, 7, 7, 7); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 232398109278351360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 6, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 244811420401807360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 11, 21, 19, 43, 0); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 250345338962063360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 5, 5, 5, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 255197859283087360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 9, 19, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 256860816933007360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + { + var now = new DateTime(2021, 12, 19, 13, 13, 11); + multiShardingOrders.Add(new MultiShardingOrder() + { + Id = 260394098622607360, + Name = $"{now:yyyy/MM/dd HH:mm:ss}", + CreateTime = now + }); + } + #endregion using (var tran = virtualDbContext.Database.BeginTransaction()) { await virtualDbContext.AddRangeAsync(userMods); @@ -280,6 +358,7 @@ namespace ShardingCore.Test5x await virtualDbContext.AddRangeAsync(logYears); await virtualDbContext.AddRangeAsync(logMonthLongs); await virtualDbContext.AddRangeAsync(logYearkLongs); + await virtualDbContext.AddRangeAsync(multiShardingOrders); await virtualDbContext.SaveChangesAsync(); tran.Commit();