Если вы храните свои записи в базе данных, вы должны действительно изучить возможности, доступные там, чтобы генерировать уникальные суррогатные ключи. В SQLServer это будет поле IDENTITY, и в Oracle это будет поле, которое использует SEQUENCE для генерации нового значения.
Если есть веская причина, почему вы не можете использовать базу данных для генерации уникального ключа, вы должны смотреть на что-то вроде Guid
- который имеет раздо большую вероятность, чем манипуляции даты и время для создания уникального значения , Гиды могут быть тривиально преобразованы в строки, поэтому ваш идентификатор будет строкой в этом случае.
То, что вы делаете с хешами, не является хорошей идеей - ничто не гарантирует, что хеши будут уникальными - и во многих случаях они действительно сталкиваются. Гиды - не обеспечивают 100% гарантию уникальности через машины, но на одной машине они всегда должны быть уникальными. И даже на машинах их шансы на столкновение крайне удалены. Кроме того, использование машинного времени в качестве способа создания базового значения зависит от условий гонки (например, описывает Эрик).
Гиды - это 128-битные значения, поэтому вы не можете представлять их как простые int
или long
. Это потребует от вас использовать строку в качестве идентификаторов, что может быть или не быть возможно в вашем случае, в зависимости от других соображений (например, независимо от того, управляете ли вы моделью данных). Если использовать их, используя Guid очень просто:
string customerId = Guid.NewGuid().ToString(); // fetch new guid and save as string
string orderNumber = Guid.NewGuid().ToString(); // same story here...
Если вы действительно должны использовать числовой идентификатор, и вы готовы легко отказаться от масштабирования приложения на нескольких серверах, вы могли бы использовать автоинкрементный глобальный номер для предоставления уникального ключа. Вам нужно будет занести это число со следующего доступного значения (max + 1) из вашей базы данных при запуске приложения. Вы также должны были бы защитить это значение от одновременного использования из нескольких потоков.Я бы обернуть эту ответственность в классе:
class static UniqueIDGenerator
{
// reads Max+1 from DB on startup
private static long m_NextID = InitializeFromDatabase();
public static long GetNextID() { return Interlocked.Increment(ref m_NextID); }
}
EDIT:В этот день и возраст, веские причины для генерации уникальных идентификаторов в вашем прикладном уровне, а не на базе очень редко , Вы действительно должны использовать возможности, предоставляемые базой данных.
Чисто теоретически, хэши могут столкнуться. – 2010-02-15 16:11:00
Несомненно, это не уникально, что вы ищете, просто следующий порядковый номер ... Я согласен с тем, что люди говорят об использовании столбца идентификации. – Paddy
@Developer Art: Ничего теоретического о нем. Хеши сталкиваются * все время *. Их доступно только около четырех миллиардов, поэтому, конечно, они столкнутся. –