C#版ObjectId

我希望有一个简单的方法实现分布式,解决HIS的数据库压力大的情况。而最需要有类似GUID的形式生成主键。但我拿不准纯数字ID段还是GUID一类的文本ID。最终在mongodb的obejctId的方案中得到启发,决定应用类似方案。

很高兴找到以下文章

https://www.cnblogs.com/gaochundong/archive/2013/04/24/csharp_generate_mongodb_objectid.html

ObjectId 是一个 12 Bytes 的 BSON 类型,其包含:

  1. 4 Bytes 自纪元时间开始的秒数
  2. 3 Bytes 机器描述符
  3. 2 Bytes 进程ID
  4. 3 Bytes 随机数

虽然发现文中时间部分似乎有错,但一直对于其3位byte的机器描述如何得到不知所然,以上博主给了可运行的代码真是受益非浅,在此再次感谢。

调整时间部分函数

1private static byte[] GenerateTimeNowBytes() 2{ 3 var now = DateTime.UtcNow; 4 var diff = now - Epoch;//取与1970的时间差 5 int timeVal = Convert.ToInt32(Math.Floor(diff.TotalSeconds));//取时间差的总秒数 6 //return BitConverter.GetBytes(timeVal);//低位数在前面的字节,字符串格式化时,排序变得无序 7 return GetIntBytes(timeVal, 4); 8}

为了得到的ObjectId的字符串可用于实际先后的排序,所以自己写了两个数字转字节和字节转数字的方法,替换BitConverter的类似方法

1private static byte[] GetIntBytes(int val, int len) 2{ 3 byte[] b = new byte[len]; 4 for (int i = 0; i<len; i++) 5 { 6 int shift = 8 * (len - 1 - i); 7 b[i] = (byte)(val >> shift); 8 } 9 return b; 10} 11 12private static int ConvertInt32(byte[] b) 13{ 14 uint ival = 0; 15 int len = b.Length; 16 for (int i = 0; i < len; i++) 17 { 18 int shift = 8 * (len - 1 - i); 19 ival = ival | (uint)(b[i] << shift); 20 } 21 return (int)ival; 22}

 于是原文的生成方法修改如下

1public static byte[] Generate() 2{ 3 var oid = new byte[12]; 4 var copyidx = 0; 5 byte[] timeByte = GenerateTimeNowBytes(); 6 //DateTime curTime = BytesToTime(timeByte); 7 Array.Copy(timeByte, 0, oid, copyidx, 4); 8 copyidx += 4; 9 10 Array.Copy(_machineHash, 0, oid, copyidx, 3); 11 copyidx += 3; 12 13 Array.Copy(_processId, 0, oid, copyidx, 2); 14 copyidx += 2; 15 16 //byte[] cntBytes = BitConverter.GetBytes(GenerateCounter()); 17 byte[] cntBytes = GetIntBytes(GenerateCounter(), 3); 18 Array.Copy(cntBytes, 0, oid, copyidx, 3); 19 20 return oid; 21}

View Code

 以下是mongo驱动的实现

https://github.com/mongodb/mongo-csharp-driver

https://github.com/mongodb/mongo-csharp-driver/blob/ec74978f7e827515f29cc96fba0c727828e8df7c/src/MongoDB.Bson/ObjectModel/ObjectId.cs

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )