v8: Создание своего уникального кода для справочникаОднажды мне понадобилось создать свой уникальный код для справочника, т.к. поле Код было занято. Я столкнулся с тем, что начали появляться дубли кодов, когда пользователи одновременно записывали два элемента справочника.
Здесь метод решения этой проблемы. | | Автор статьи: Последняя редакция №1 от 20.09.06 URL: http://kb.mista.ru/article.php?id=370 | |
Ключевые слова: запросы,транзакция,конкуренция
Тема горячо обсуждалась здесь: v8: v8: У меня появились дубли уникального кода, что делать?
Процедура ПередЗаписью(Отказ)
Если Не Отказ И НЕ ЭтоГруппа Тогда
//Здесь сложное условие определения, нужно ли устанавливать уникальный код.
Если ЗначениеНеЗаполнено(УникальныйКод) Или ЭтоНовый() ИЛИ ЗначениеНеЗаполнено(Ссылка.ПолучитьОбъект().УникальныйКод) Тогда
Префикс = СокрЛП(ПланыОбмена.Подразделения.ЭтотУзел().Код);
УникальныйКод=обПолучитьНовыйКод(Метаданные.Справочники.Договоры, Префикс, "УникальныйКод", Метаданные.Справочники.Договоры.Реквизиты.УникальныйКод.Тип.КвалификаторыСтроки.Длина);
КонецПроцедуры
Функция обПолучитьНовыйКод(МДОбъект, Префикс, Реквизит, Длина) Экспорт //fixin 20060728
П=обТипОбъектаПоМетаданным(МДОбъект);
Имя=МДОбъект.Имя;
Запрос=Новый Запрос("ВЫБРАТЬ
| МАКСИМУМ(Договоры.Код) КАК Зн
|ИЗ
| Справочник.Договоры КАК Договоры
|ГДЕ
| Договоры.Код ПОДОБНО &Шаблон
|
|ДЛЯ ИЗМЕНЕНИЯ");
//Очень важно использовать ДЛЯ ИЗМЕНЕНИЯ - чтобы гарантированно код был уникальным
Запрос.Текст=СтрЗаменить(Запрос.Текст, "Договоры", Имя);
Запрос.Текст=СтрЗаменить(Запрос.Текст, "Справочник", П.ИмяЕЧ);
Запрос.Текст=СтрЗаменить(Запрос.Текст, "Код", Реквизит);
Запрос.УстановитьПараметр("Шаблон", Префикс+"%"); //ПОДОБНО "АВ%", например, хотя логичнее искать цифры
Выборка=Запрос.Выполнить().Выбрать();
ДлинаПрефикса=СтрДлина(Префикс);
Выборка.Следующий();
Если Выборка.Зн<>Null Тогда
МаксКод=Число(Сред(Выборка.Зн, ДлинаПрефикса+1));
Иначе
МаксКод=0;
КонецЕсли;
МаксКод=МаксКод+1; //Увеличиваем максимальный код
Рез=Префикс+Формат(МаксКод, "ЧЦ="+Формат(Длина-ДлинаПрефикса,"ЧГ=")+"; ЧВН=; ЧГ=");
Возврат Рез;
КонецФункции
Итак, важные моменты:
Вся запись объекта происходит в одной транзакции, поэтому достаточно использовать ДЛЯ ИЗМЕНЕНИЯ в запросе к договорам, чтобы другие процессы не смогли прочитать справочник договора, пока не завершится транзакция записиНа этом я прокололся, поэтому обратите внимание: если при записи происходит ошибка блокировки и пользователь не закрыл карточку, то даже у нового объекта уникальный код уже установлен, т.к. уже прошел код по установке уникального кода. Поэтому используется такое сложное условие для определения нужно ли устанавливать уникальный код.
Код отлаживался с помощью запуска двух процессов, один из которых выдавал Предупреждение, все работает ОК. |