Pregunta

El siguiente código se puede encontrar en la clase NHibernate.Id.GuidCombGenerator. El algoritmo crea guids secuenciales (peine) en base a la combinación de un "aleatorio" guid con un DateTime. Tengo un par de preguntas relacionadas con las líneas que he marcado con * 1) y * 2) a continuación:

private Guid GenerateComb()
{
    byte[] guidArray = Guid.NewGuid().ToByteArray();

    // *1)
    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;

    // *2)
    // 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);
}

En primer lugar, por * 1), ¿no sería mejor tener una fecha más reciente, como el fechabase, por ejemplo, 2000-01-01, con el fin de hacer espacio para más valores en el futuro?

En cuanto a * 2), ¿por qué nos preocupa por la exactitud de DateTime en SQL Server, cuando sólo estamos interesados ??en los bytes de la fecha y hora de todos modos, y nunca tienen la intención de almacenar el valor en un campo de fecha y hora de SQL Server? ¿No sería mejor usar toda la precisión disponible a partir DateTime.Now?

¿Fue útil?

Solución

Re 1: no hay ninguna relevancia para el valor real día, los dos bytes utilizados a partir del valor simplemente ruedan sobre 65536 días después de 1/1/1900. Lo único que importa es que los valores son más o menos secuencial. La dBase va a ser un poco ineficiente en el verano de 2079, nadie se dará cuenta.

Re 2: sí, no tiene sentido. Pero la misma historia, el valor real no importa.

El algoritmo es cuestionable, jugar con la singularidad garantizada de GUID es una proposición difícil. Vas a tener que depender de alguien en el equipo de NHibernate tener conocimiento de información privilegiada que esto funciona sin problemas. Si lo cambia, usted es responsable de romperlo.

Otros consejos

COMB fue creado específicamente para utilizar de manera eficiente los GUID como un índice agrupado en SQL Server. Es por eso que está escrito en torno a un comportamiento específico de SQL Server.

Estoy muy tarde para este partido, pero pensé que me gustaría compartir la intención original del COMB.

Me empezó a usar NHibernate en el '04 y que quería utilizar GUID para nuestros documentos de identidad. Después de algunas investigaciones he encontrado que SQL Server no fue eficiente en el uso de GUID completamente al azar como un / índice agrupado clave primaria porque quería guardarlos en orden y tendría que hacer inserto en el centro de la mesa (divisiones de página). Tengo el algoritmo para el peine de este artículo: http://www.informit.com /articles/article.aspx?p=25862 por Jimmy Nilsson que es una descripción muy completa de por qué los peines son como son (y una buena lectura). Empecé a usar un generador personalizado para generar peines y los NHibernate lo recogió como un generador incorporado.

COMB no puede producir ID en orden en otros servidores. Nunca he investigado a él.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top