1
1
using System ;
2
+ using System . Diagnostics ;
2
3
using NHibernate . Engine ;
3
4
4
5
namespace NHibernate . Id
@@ -36,21 +37,50 @@ public partial class GuidCombGenerator : IIdentifierGenerator
36
37
/// <returns>The new identifier as a <see cref="Guid"/>.</returns>
37
38
public object Generate ( ISessionImplementor session , object obj )
38
39
{
39
- return GenerateComb ( ) ;
40
+ return GenerateComb ( Guid . NewGuid ( ) , DateTime . UtcNow ) ;
40
41
}
41
42
42
43
/// <summary>
43
44
/// Generate a new <see cref="Guid"/> using the comb algorithm.
44
45
/// </summary>
45
- private Guid GenerateComb ( )
46
+ protected static Guid GenerateComb ( in Guid guid , DateTime utcNow )
46
47
{
47
- byte [ ] guidArray = Guid . NewGuid ( ) . ToByteArray ( ) ;
48
+ #if NET8_0_OR_GREATER
49
+ Span < byte > guidArray = stackalloc byte [ 16 ] ;
50
+ Span < byte > msecsArray = stackalloc byte [ sizeof ( long ) ] ;
51
+ Span < byte > daysArray = stackalloc byte [ sizeof ( int ) ] ;
48
52
49
- DateTime now = DateTime . UtcNow ;
53
+ var bytesWritten = guid . TryWriteBytes ( guidArray ) ;
54
+ Debug . Assert ( bytesWritten ) ;
50
55
51
56
// Get the days and milliseconds which will be used to build the byte string
52
- TimeSpan days = new TimeSpan ( now . Ticks - BaseDateTicks ) ;
53
- TimeSpan msecs = now . TimeOfDay ;
57
+ TimeSpan days = new TimeSpan ( utcNow . Ticks - BaseDateTicks ) ;
58
+ TimeSpan msecs = utcNow . TimeOfDay ;
59
+
60
+ // Convert to a byte array
61
+ // Note that SQL Server is accurate to 1/300th of a millisecond so we divide by 3.333333
62
+
63
+ bytesWritten = BitConverter . TryWriteBytes ( daysArray , days . Days )
64
+ && BitConverter . TryWriteBytes ( msecsArray , ( long ) ( msecs . TotalMilliseconds / 3.333333 ) ) ;
65
+ Debug . Assert ( bytesWritten ) ;
66
+
67
+ msecsArray . Reverse ( ) ;
68
+
69
+ // Copy the bytes into the guid
70
+ //Array.Copy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2);
71
+ guidArray [ 10 ] = daysArray [ 1 ] ;
72
+ guidArray [ 11 ] = daysArray [ 0 ] ;
73
+
74
+ //Array.Copy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4);
75
+ msecsArray [ ^ 4 ..] . CopyTo ( guidArray [ ^ 4 ..] ) ;
76
+ return new Guid ( guidArray ) ;
77
+ #else
78
+
79
+ byte [ ] guidArray = guid . ToByteArray ( ) ;
80
+
81
+ // Get the days and milliseconds which will be used to build the byte string
82
+ TimeSpan days = new TimeSpan ( utcNow . Ticks - BaseDateTicks ) ;
83
+ TimeSpan msecs = utcNow . TimeOfDay ;
54
84
55
85
// Convert to a byte array
56
86
// Note that SQL Server is accurate to 1/300th of a millisecond so we divide by 3.333333
@@ -66,6 +96,7 @@ private Guid GenerateComb()
66
96
Array . Copy ( msecsArray , msecsArray . Length - 4 , guidArray , guidArray . Length - 4 , 4 ) ;
67
97
68
98
return new Guid ( guidArray ) ;
99
+ #endif
69
100
}
70
101
71
102
#endregion
0 commit comments