Come osservato da Alberto Ferrari
e discusso qui su StackOverflow
, Microsoft SQL Server ordina i GUID confrontando i byte in un ordine specifico. Poiché MySQL ordinerà un BINARY(16)
"semplicemente", tutto ciò che dobbiamo fare è riordinare i byte durante la lettura/scrittura nel database.
NHibernate ci consente di definire tipi di dati personalizzati, che possono essere utilizzati nelle mappature tra database e oggetti. Ho implementato un BinaryGuidType
, in grado di riordinare i byte prodotti da Guid.ToByteArray()
in base al modo in cui MSSQL ordina i GUID e li riordina nel formato accettato da Guid(byte[])
costruttore.
L'ordine dei byte è simile al seguente:
int[] ByteOrder = new[] { 10,11,12,13,14,15,8,9,6,7,4,5,0,1,2,3 };
Salvataggio di un System.Guid
a un BINARY(16)
va così:
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);
Rileggere i byte in un System.Guid
va così:
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];
}
Codice sorgente completo per BinaryGuidType
qui.
Questo sembra funzionare bene. Creando e rendendo persistenti 10.000 nuovi oggetti in una tabella, vengono archiviati in modo completamente sequenziale, senza segni di frammentazione dell'indice.