zoukankan      html  css  js  c++  java
  • C#实现SQLSERVER数据库中有序GUID生成(NewSequentialId)

    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     }

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

  • 相关阅读:
    Java 中String、StringBuffer、StringBuilder的差别
    [转载]StringBuffer versus String
    二维数组的连续子数组的最大和
    一位数组的最大和
    js中常见的去重方式
    魅族2016Java互联网方向其中一道笔试题--青蛙跳台阶问题
    美团在线编程2016--最大差值
    [转载]MySQL开发中常用的查询语句总结
    实现字符串全排列
    笔试题---最大子序列和
  • 原文地址:https://www.cnblogs.com/huixch/p/4966673.html
Copyright © 2011-2022 走看看