Като наблюдаван от Алберто Ферари
и обсъдени тук в StackOverflow
, Microsoft SQL Server сортира GUID, като сравнява байтовете в определен ред. Тъй като MySQL ще сортира BINARY(16)
"направо", всичко, което трябва да направим, е да пренаредим байтовете при четене/записване в базата данни.
NHibernate ни позволява да дефинираме персонализирани типове данни, които могат да се използват при съпоставяния между база данни и обекти. Внедрил съм BinaryGuidType
, способен да пренарежда байтовете, произведени от Guid.ToByteArray()
според начина, по който MSSQL сортира GUID и ги пренарежда обратно във формата, приет от Guid(byte[])
конструктор.
Редът на байтовете изглежда така:
int[] ByteOrder = new[] { 10,11,12,13,14,15,8,9,6,7,4,5,0,1,2,3 };
Записване на System.Guid
към BINARY(16)
става така:
var bytes = ((Guid) value).ToByteArray();
var reorderedBytes = new byte[16];
for (var i = 0; i < 16; i++)
{
reorderedBytes[i] = bytes[ByteOrder[i]];
}
NHibernateUtil.Binary.NullSafeSet(cmd, reorderedBytes, index);
Четене на байтовете обратно в System.Guid
става така:
var bytes = (byte[]) NHibernateUtil.Binary.NullSafeGet(rs, names[0]);
if (bytes == null || bytes.Length == 0) return null;
var reorderedBytes = new byte[16];
for (var i = 0 ; i < 16; i++)
{
reorderedBytes[ByteOrder[i]] = bytes[i];
}
Пълен изходен код за BinaryGuidType
тук.
Това изглежда работи добре. Създавайки и запазвайки 10 000 нови обекта в таблица, те се съхраняват напълно последователно, без признаци на фрагментация на индекса.