SQLServer数据库之C#实现SQLSERVER数据库中有序GUID生成(NewSequentialId)
小标 2018-10-19 来源 : 阅读 1683 评论 0

摘要:本文主要向大家介绍了SQLServer数据库之C#实现SQLSERVER数据库中有序GUID生成(NewSequentialId),通过具体的内容向大家展现,希望对大家学习SQLServer数据库有所帮助。

本文主要向大家介绍了SQLServer数据库之C#实现SQLSERVER数据库中有序GUID生成(NewSequentialId),通过具体的内容向大家展现,希望对大家学习SQLServer数据库有所帮助。

GUID作为数据库主键由于其无序性所以性能不怎么好,SQL Server中有个函数NewSequentialId可以生成有序的GUID,由于在程序中需要用到,就用C#实现了一下,生成的GUID格式基本和SQL Server一致。
程序代码参考了rpcrt4.dll中UuidCreateSequential的实现。

  1     public class GuidHelper
  2     {
  3         private static bool initialised;
  4         private static int count;
  5 
  6         private static long time;
  7         private static long timelast;
  8         private static ushort sequence;
  9 
 10         private static byte[] address; //网卡MAC
 11         private static readonly object locker = new object();
 12         public static Guid NewSequentialId()
 13         {
 14             lock(locker)
 15             {
 16                 if (!initialised)
 17                 {
 18                     timelast = UuidGetSystemTime();
 19                     count = TICKS_PER_CLOCK_TICK;
 20                     Random rand = new Random(1);
 21                     sequence = (ushort)(((rand.Next(1, 32767) & 0xFF) << 8) + rand.Next(1, 32767) & 0xFF);
 22                     sequence &= 0x1FFF;
 23                     address = GetAddressBytes();
 24                     initialised = true;
 25                 }
 26                 while (true)
 27                 {
 28                     time = UuidGetSystemTime();
 29                     if (time > timelast)
 30                     {
 31                         count = 0;
 32                         break;
 33                     }
 34                     if (time < timelast)
 35                     {
 36                         sequence = (ushort)((sequence + 1) & 0x1FFF);
 37                         count = 0;
 38                         break;
 39                     }
 40                     if (count < TICKS_PER_CLOCK_TICK)
 41                     {
 42                         count++;
 43                         break;
 44                     }
 45                 }
 46 
 47                 timelast = time;
 48                 time += count;
 49 
 50                 byte[] guidArray = new byte[16];
 51 
 52                 uint data1 = (uint)(time & 0xffffffff);
 53                 ushort data2 = (ushort)((time >> 32) & 0xffff);
 54                 ushort data3 = (ushort)((time >> 48) & 0x0fff);
 55                 /* This is a version 1 UUID */
 56                 data3 |= (1 << 12);
 57 
 58                 guidArray[3] = (byte)data1;
 59                 guidArray[2] = (byte)(data1 >> 8);
 60                 guidArray[1] = (byte)(data1 >> 16);
 61                 guidArray[0] = (byte)(data1 >> 24);
 62                 guidArray[5] = (byte)data2;
 63                 guidArray[4] = (byte)(data2 >> 8);
 64                 guidArray[7] = (byte)data3;
 65                 guidArray[6] = (byte)(data3 >> 8);
 66                 guidArray[8] = (byte)(sequence & 0xff);
 67                 guidArray[9] = (byte)((sequence & 0x3f00) >> 8);
 68                 guidArray[9] |= 0x80;
 69                 Array.Copy(address, 0, guidArray, 10, 6);
 70 
 71                 return new Guid(guidArray);
 72             }//locker
 73         }//UuidCreateSequential
 74 
 75         private static readonly int TICKS_PER_CLOCK_TICK = 1000;
 76         private static readonly int SECSPERDAY = 86400;
 77         private static readonly int TICKSPERSEC = 10000000;
 78         private static readonly long SECS_15_OCT_1582_TO_1601 = (17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY;
 79         private static readonly long TICKS_15_OCT_1582_TO_1601 = SECS_15_OCT_1582_TO_1601 * TICKSPERSEC;
 80         private static long UuidGetSystemTime()
 81         {
 82             DateTime dt = DateTime.Now;
 83             var ft = dt.ToFileTime();
 84             ft += TICKS_15_OCT_1582_TO_1601;
 85             return ft;
 86         }
 87 
 88         private static byte[] GetAddressBytes()
 89         {
 90             byte[] bytes;
 91             NetworkInterface[] nic = NetworkInterface.GetAllNetworkInterfaces();
 92             if (nic == null || nic.Length < 1)
 93             {
 94                 bytes = new byte[6];
 95                 bytes[0] = 0x01;
 96                 return bytes;
 97             }
 98             bytes = nic[0].GetPhysicalAddress().GetAddressBytes();
 99             return bytes;
100         }
101     }

代码写的比较粗糙,不过功能已经实现,有需要的朋友可以自行优化

本文由职坐标整理并发布,希望对同学们学习SQL Server有所帮助,更多内容请关注职坐标数据库SQL Server数据库频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程