public static class Generator
{
[DllImport("rpcrt4.dll", SetLastError = true)]
public static extern int UuidCreateSequential(out Guid guid);
private const int RPC_S_OK = 0;
public static Guid CreateRpcrt4Guid()
{
Guid guid;
int result = UuidCreateSequential(out guid);
if (result == RPC_S_OK)
return guid;
else
return Guid.NewGuid();
}
public static Guid CreateSecuentialGuid()
{
byte[] uid = Guid.NewGuid().ToByteArray();
byte[] binDate = BitConverter.GetBytes(DateTime.UtcNow.Ticks);
byte[] secuentialGuid = new byte[uid.Length];
secuentialGuid[0] = uid[0];
secuentialGuid[1] = uid[1];
secuentialGuid[2] = uid[2];
secuentialGuid[3] = uid[3];
secuentialGuid[4] = uid[4];
secuentialGuid[5] = uid[5];
secuentialGuid[6] = uid[6];
// set the first part of the 8th byte to '1100' so
// later we'll be able to validate it was generated by us
secuentialGuid[7] = (byte)(0xc0 | (0xf & uid[7]));
// the last 8 bytes are sequential,
// it minimizes index fragmentation
// to a degree as long as there are not a large
// number of Secuential-Guids generated per millisecond
secuentialGuid[9] = binDate[0];
secuentialGuid[8] = binDate[1];
secuentialGuid[15] = binDate[2];
secuentialGuid[14] = binDate[3];
secuentialGuid[13] = binDate[4];
secuentialGuid[12] = binDate[5];
secuentialGuid[11] = binDate[6];
secuentialGuid[10] = binDate[7];
return new Guid(secuentialGuid);
}
public static Guid CreateCombGuid()
{
byte[] guidArray = Guid.NewGuid().ToByteArray();
DateTime baseDate = new DateTime(1900, 1, 1);
DateTime now = DateTime.Now;
// Get the days and milliseconds which will be used to build the byte string
TimeSpan days = new TimeSpan(now.Ticks - baseDate.Ticks);
TimeSpan msecs = now.TimeOfDay;
// Convert to a byte array
// Note that SQL Server is accurate to 1/300th of a millisecond so we divide by 3.333333
byte[] daysArray = BitConverter.GetBytes(days.Days);
byte[] msecsArray = BitConverter.GetBytes((long)(msecs.TotalMilliseconds / 3.333333));
// Reverse the bytes to match SQL Servers ordering
Array.Reverse(daysArray);
Array.Reverse(msecsArray);
// Copy the bytes into the guid
Array.Copy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2);
Array.Copy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4);
return new Guid(guidArray);
}
}
每种方法只生成10条记录,结果如下
rpcrt4: | Secuential: | Comb: |
f8373adb-cf34-11e2-be8d-d43d7e333b2c f8373adc-cf34-11e2-be8d-d43d7e333b2c f8373add-cf34-11e2-be8d-d43d7e333b2c f8373ade-cf34-11e2-be8d-d43d7e333b2c f8373adf-cf34-11e2-be8d-d43d7e333b2c f8373ae0-cf34-11e2-be8d-d43d7e333b2c f8373ae1-cf34-11e2-be8d-d43d7e333b2c f8373ae2-cf34-11e2-be8d-d43d7e333b2c f8373ae3-cf34-11e2-be8d-d43d7e333b2c f8373ae4-cf34-11e2-be8d-d43d7e333b2c | e8edcc23-9c22-c3b1-04d1-08d07e5fad6c | 65d8b46f-ea29-41f8-af76-a1d600e29f85 2c95c4c2-aca4-46de-b842-a1d600e29f85 c6f054ea-dbb4-432c-aed3-a1d600e29f85 2b47c23c-ac18-467c-8c2d-a1d600e29f85 4dbe1536-ccb1-4fc4-b145-a1d600e29f85 cccd4c08-6c52-4b12-90fc-a1d600e29f85 f6f07bde-5108-43c0-9294-a1d600e29f85 921a018f-9545-447b-8c99-a1d600e29f85 fbc560a3-acbe-48da-9b06-a1d600e29f85 bbfbbe7f-2bc6-4bd7-bbae-a1d600e29f85 |
单从结果上看,第一种使用起来更方便些.
但这种方法有一个问题,就是在SQL SERVER中排序还是会乱,所以在需要排序的时候,需要对这种生成方式进行简单处理,增加一点代码
byte[] guidBytes = guid.ToByteArray(); Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); Array.Reverse(guidBytes, 6, 2);
最终代码变为:
public static Guid CreateRpcrt4Guid() { Guid guid; int result = UuidCreateSequential(out guid); if (result == RPC_S_OK) { byte[] guidBytes = guid.ToByteArray(); Array.Reverse(guidBytes, 0, 4); Array.Reverse(guidBytes, 4, 2); Array.Reverse(guidBytes, 6, 2); return new Guid(guidBytes); } else return Guid.NewGuid(); }