2010-04-14 1 views
1

Следующий код может быть найден в классе NHibernate.Id.GuidCombGenerator. Алгоритм создает последовательные (гребенчатые) наборы, основанные на объединении «случайного» guid с DateTime. У меня есть несколько вопросов, связанных с линиями, которые я помеченных * 1) и * 2) ниже:Несколько вопросов о GuidCombGenerator NHibernate

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); 
} 

Прежде всего, для * 1), не было бы лучше иметь более недавняя дата как baseDate, например 2000-01-01, чтобы освободить место для большего количества ценностей в будущем?

Относительно вопроса * 2), почему мы заботимся о точности DateTimes в SQL Server, когда нас интересуют только байты datetime и никогда не намерены хранить это значение в поле даты и времени SQL Server? Не было бы лучше использовать всю точность, доступную в DateTime.Now?

+0

Мне интересно, почему он использует DateTime.Now вместо DateTime.UtcNow? Если вы создаете контуры на серверах в разных часовых поясах, смещение будет отличаться, а подсказки не будут последовательными. – MartinF

ответ

4

Re 1: не имеет значения для фактического значения дня, два байта, используемые из значения, просто свернутся на 65536 дней после 1/1/1900. Единственное, что имеет значение, это то, что значения примерно последовательны. Дабад будет немного неэффективен летом 2079 года, никто не заметит.

Re 2: да, не имеет смысла. Но такая же история, фактическая ценность не имеет значения.

Алгоритм сомнительный, беспорядок с гарантированной уникальностью Гидов является сложным предложением. Вам нужно будет полагаться на кого-то в команде nHibernate, имеющей инсайдерские знания, что это работает без проблем. Если вы измените его, вы можете его сломать.

1

COMB был создан специально для эффективного использования GUID как кластерного индекса в SQL Server. Вот почему это написано вокруг специфического поведения SQL Server.

Я очень опаздываю на эту вечеринку, но я думал, что поделюсь оригинальным намерением COMB.

Я начал использовать nHibernate в '04, и мы хотели использовать GUID для наших идентификаторов. После некоторых исследований я обнаружил, что SQL Server неэффективен при использовании полностью случайных GUID в качестве первичного ключа/кластерного индекса, потому что он хотел сохранить их в порядке и должен был бы вставлять их в середину таблицы (разбиение страниц). Я получил алгоритм для COMB из этой статьи: http://www.informit.com/articles/article.aspx?p=25862 от Jimmy Nilsson, который является очень подробным описанием того, почему COMB - это то, как они есть (и хорошее чтение). Я начал использовать собственный генератор для создания COMB, и они NHibernate выбрали его как встроенный генератор.

COMB не может создавать идентификаторы в заказе на других серверах. Я никогда не исследовал его.