使用SQL生成DateTime.Ticks
在项目中我需要使用到一个随机数(Random Number),该随机数将作为 Hashtable 中的 Key 用于唯一索引数据,所以需要保持单机唯一性。
同时该随机数还需要具备可排序性以便对数据进行排序。
此时,我可以考虑使用随机字符串《C#生成MongoDB中的ObjectId》,这里的 ObjectId 具备单机唯一性和可排序性。
但另一个需求是,我需要该随机数为 int 或 long 类型,以便与依赖的 Service 进行通信,部分取代 TransactionId 或 Token 的职责。
所以,很自然的我就想到了时间。
查看了 MSDN 上关于 DateTime.MinValue 和 DateTime.Ticks 的定义,考虑到我所设计的服务每秒不会产生多于 10000000 的数据,
我决定使用 DateTime.Ticks 作为随机数的起始点,这样就有了下面这段代码。
1 public static class UniqueId 2 { 3 private static long _sequence = DateTime.UtcNow.Ticks; 4 5 public static long Generate() 6 { 7 return Interlocked.Increment(ref _sequence); 8 } 9 10 public static long Sequence 11 { 12 get 13 { 14 return _sequence; 15 } 16 } 17 }
业务逻辑中会将 UniqueId 存储到 SQL Server 数据库中,使用 bigint 类型进行存储。
1 CREATE TABLE [TableName]( 2 [UniqueId] [bigint] NOT NULL, 3 );
这样,在数据库中,该 UniqueId 即可作为索引,也可进行排序。
现在问题来了,我需要将一个较老的服务升级到新的服务中,做 Date Migration。
老的服务中没有 UniqueId 逻辑和数据,这就需要我在数据迁移时为每条表数据生成该 UniqueId。
显然,SQL Server 不会帮我做这件事,我需要使用 SQL Script 来生成 UniqueId。
DateTime.Ticks 的定义是:
A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond.
1 Tick 等于千万分之一秒,或万分之一毫秒。
The value represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001, which represents DateTime.MinValue.
DateTime.Ticks 代表着从时间 "00:00:00.0000000, January 1, 0001" 至当前时间的 Tick 总数。
这样,我们就可以根据其原理通过 SQL 来计算其值。
1 DECLARE @current_datetime DATETIME; 2 DECLARE @days_from_0001_to_1900 BIGINT; 3 DECLARE @ticks_per_millisecond BIGINT; 4 DECLARE @ticks_per_day BIGINT; 5 DECLARE @millisecond_of_time BIGINT; 6 DECLARE @ticks_of_days BIGINT; 7 DECLARE @ticks_of_time BIGINT; 8 DECLARE @ticks BIGINT; 9 10 SET @current_datetime = GETUTCDATE(); 11 SET @days_from_0001_to_1900 = 693595; 12 SET @ticks_per_millisecond = 10000; 13 SET @ticks_per_day = 24 * 3600 * 1000 * @ticks_per_millisecond; 14 SET @millisecond_of_time = 15 DATEPART(MILLISECOND, @current_datetime) 16 + (DATEPART(SECOND, @current_datetime)) * 1000 17 + (DATEPART(MINUTE, @current_datetime)) * 60000 18 + (DATEPART(HOUR, @current_datetime)) * 3600000; 19 SET @ticks_of_days = CAST(@days_from_0001_to_1900 + DATEDIFF(DAY, 0, @current_datetime) AS BIGINT) * @ticks_per_day; 20 SET @ticks_of_time = @millisecond_of_time * @ticks_per_millisecond; 21 SET @ticks = @ticks_of_days + @ticks_of_time; 22 23 SELECT @current_datetime, @ticks
这段 SQL 脚本的运行结果是:
我们通过下面这段 C# 代码来验证结果。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 DateTime d1 = new DateTime(2014, 04, 01, 02, 52, 54, 153, DateTimeKind.Utc); 6 DateTime d2 = DateTime.Parse("2014-04-01 02:52:54.153"); 7 DateTime d3 = DateTime.Parse("2014-04-01 02:52:54.153", 8 CultureInfo.CurrentCulture, DateTimeStyles.AdjustToUniversal); 9 10 Console.WriteLine(d1.Ticks); 11 Console.WriteLine(d2.Ticks); 12 Console.WriteLine(d3.Ticks); 13 14 Console.ReadKey(); 15 } 16 }
瞧,它们的结果一致为 635319175741530000。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)