public int GenPurchaseOrderNum()
{
Random random = new Random();
_uniqueNum = random.Next(13287, 21439);
return UniqueNum;
}
Я удалил ограничение на уникальность данных из столбца PONumber в дб, потому что сотрудник должен только генерировать отделение связи #, когда соглашение установлено. Иначе отделение связи # имело бы 0.
Номер отделения связи раньше имел ограничение на уникальность данных, это вынуждает сотрудника генерировать отделение связи во всех случаях, таким образом, дб не бросает ошибку ограничения на уникальность данных.
Так как я удалил ограничение на уникальность данных, любая кавычка не имеет отделения связи, будет нести 0 значений. Иначе уникальное значение сгенерировано для отделения связи #. Однако у меня нет ограничения на уникальность данных в дб, который мешает мне знать, генерировало ли приложение отделение связи #, уникально или нет.
Что мне делать?
Я надеюсь, что мой вопрос достаточно ясен
GUID - это немного накладно. В частности, похоже, что вам нужен человекочитаемый номер для PO#, что делает GUID непрактичным. Я бы больше склонялся к использованию следующего сценария.
Это взгляд с 20-километровой высоты.
Из того, что вы написали, кажется, что вы идете неверным путем: Вы путаете случайность с уникальностью.
Вы убрали ограничение, специфичное для домена, чтобы оно соответствовало написанному вами коду. Если значение PONumber не имеет никакого другого значения, кроме уникальности, попросите базу данных сгенерировать его для вас, или сгенерируйте GUID (если база данных не может), что даст вам некоторую гарантию того, что сгенерированное значение будет уникальным.
В противном случае вся тяжелая работа ложится на вас. Вам придется генерировать уникальное значение, помня обо всех потоковых и транзакционных проблемах.
Как и на предыдущих плакатах, я бы рекомендовал уникальное значение вместо случайного. Генератор последовательности, который предлагает Ремус, вероятно, лучший подход.
Однако, если вам действительно действительно нужно случайное значение, я бы рекомендовал использовать RNGCryptoServiceProvider вместо класса Random, потому что он более случайный. Посетите MSDN для дополнительной информации . Также есть хороший вопрос StackOverflow по RNGCryptoServiceProvider .
В подобных ситуациях, когда есть поле или набор полей, которые просто не имеют значение из-за состояния сущности, которую представляет запись, мне иногда нравится разбивать таблицу на две отдельные таблицы, которые связаны отношением 1 к 1.
Предположим, что ваша исходная таблица называется PurchaseOrder и имеет структуру, которая выглядит примерно так:
table PurchaseOrder
(
PurchaseOrderID int identity not null,
-- some other fields that are core to a purchase order
-- ...
PONumber int not null,
-- some other fields that are related to a purchase order when the deal is set
-- ...
-- define primary key on PuchaseOrderID
-- define unique constraint on PONumber field
)
Я предлагаю разбить эту таблицу на части, чтобы она выглядела примерно так:
table PurchaseOrder
(
PurchaseOrderID int identity not null,
-- some other fields that are core to a purchase order
-- ...
-- define primary key on PuchaseOrderID
)
table PurchaseOrderDealInfo
(
PurchaseOrderID int not null,
PONumber int identity not null,
-- some other fields that are related to a purchase order when the deal is set
-- ...
-- define primary key on PurchaseOrderID
-- define foreign key on PurchaseOrderID related to PurcahseOrder.PurchaseOrderID
-- define unique constraint on PONumber field
)
Теперь ваша сделка информация в отдельной таблице. Любые заказы на покупку, для которых еще не установлена сделка, просто не будут иметь соответствующей записи в таблице PurchaseOrderDealInfo. Да, вам нужно будет объединить таблицы вместе, если вы хотите получить всю информацию, относящуюся к конкретному заказу на покупку. Однако вы получаете некоторые преимущества:
Вы все еще можете применить уникальное ограничение к столбцу PONumber.
Вы можете воспользоваться функцией идентификации SQL Server, чтобы сгенерировать для вас свой PONumber
Если бы в вашей таблице были какие-либо другие столбцы, специфичные для сделки, которые вы сделали обнуляемыми, просто потому, что они не имели бы значения до тех пор, пока не будет заключена сделка. set, то, как только вы переместите эти столбцы в таблицу PurchaseOrderDealInfo, вы можете запретить использование нулей (при необходимости).
Если вы хотите получить только заказы на покупку, в которых есть сделки, вы можете просто запросить таблицу PurcahseOrderDealInfo, не задавая никаких критериев фильтрации. Конечно, если вам также нужна информация из таблицы PurchaseOrder, вам нужно будет выполнить внутреннее соединение.
UPDATE seqnces SET sequence = sequence+1 OUTPUT INSERTED.sequence WHERE key = 'somekey'
Обновлено
В SQL Server 2008 и выше вы можете иметь уникальный фильтрованный индекс, который будет действовать как ограничение для всего, что не равно 0:
create unique index idxTbaleUniquePoNumber
on <table> (po_number)
where (po_number > 0);
Вроде как съесть торт и получить его тоже...
Если вам действительно нужна серия уникальных случайных чисел в диапазоне (скажем, от 13287 до 21439), я бы создал список всех допустимых целых чисел, а затем случайным образом поменял их местами. Что-то вроде несортировки, если хотите. Это даст вам список случайных, уникальных чисел.
Фокус в том, чтобы сохранить этот список, поскольку если вы действительно хотите получить случайные числа, то на их генерацию потребуется некоторое время. Я бы поместил его в таблицу, чтобы вы могли проиндексировать его в любом месте, где он вам нужен.
Я думаю, что вы пошли по неправильному пути с самого начала, и это становится все хуже. Нет реального бизнес-обоснования или требований, сопровождающих вашу заявленную проблему, и поэтому трудно понять, как наши ответы могут удовлетворить ваши конечные цели.
Я думаю, вам следует сделать шаг назад и четко сформулировать свои цели без учета текущей физической реализации.
Как правило, системы заказов требуют уникальных PO, поэтому вам нужно иметь уникальное ограничение на это. Как правило, системы не хранят PO и "предварительные PO" одинаково. Предварительные заказы" обычно называются котировками или чем-то подобным, и они часто имеют свою собственную систему нумерации. Таким образом, обычно нет конфликта в наличии номеров NULL или 0 PO, потому что нет ничего, что не является реальным PO, хранящимся вместе с реальными PO. Даже в системах, которые хотят хранить их вместе, они просто идут вперед и присваивают им номер в той же последовательности.
Кроме того, идентификатор вполне подходит для генерации номеров PO.
Если вам действительно нужно случайное значение, вместо того, чтобы возвращать int
, вы можете использовать GUID. Они гарантированно будут уникальными:
GUID - это 128-битное целое число (16 байтов), которое может использоваться на всех компьютерах и сетях, где требуется уникальный идентификатор. Такой идентификатор имеет очень низкую вероятность дублирования.
В качестве альтернативы можно вести учет последнего использованного числа и просто увеличивать его каждый раз, когда вам нужен новый заказ на покупку. Убедитесь, что вы установили блокировку, чтобы два процесса не пытались увеличить его одновременно.
Как насчет псевдослучайных чисел? Конечно, почти все реализации случайных чисел в языковых библиотеках уже являются псевдослучайными, но есть алгоритмы, которые вы можете реализовать, которые будут создавать видимость случайности при сохранении уникальности.
Некоторые из них можно найти в списке генераторов псевдослучайных чисел . Мне нравится идея сдвигового регистра с линейной обратной связью для генерации чисел, которые не являются последовательными и имеют определенный период (то есть количество вызовов между повторяющимися числами).
Ваш автономер PK в базе данных можно использовать как уникальный номер PO... просто прочитайте и скопируйте его, когда он станет "настоящим" ненулевым номером PO.
Это не будет "случайным", но будет уникальным.
Теперь ответ для ботаников: Компьютер не может генерировать случайные числа без хаотических "случайных" семян
.