Опубликовано в блоге Вадимко/
Менеджер обмена данными - популярный и очень своеобразный продукт. В статье рассматривается решение одной из его проблем - получения нового уникального IDD.
После оптимизации проведения ключевых документов у нас начались блокировки констант. Переделывать будем эту функцию:
Функция ПолучитьНовыйИДД()
//Предусматриваем одновременное обращение к константе нескольких пользователей
Блокировка=1;
Пока Блокировка=1 Цикл
Попытка
НачатьТранзакцию();
Константа.УникальныйIDD=Константа.УникальныйIDD;//блокируем
Блокировка=0;//константа заблокирована не была - можем работать
Исключение//константа заблокирована !!
ОтменитьТранзакцию();
//Ожидание для возможности работы других пользователей (по совету Олега Яковлева из ЧПТФ "ЮСИ")
Стр=ТекущееВремя();
Пока Стр=ТекущееВремя() Цикл
КонецЦикла;
КонецПопытки;
КонецЦикла;
//Увеличиваем счетчик в константе на единицу
Константа.УникальныйIDD=Число(Константа.УникальныйIDD)+1;
Рез=Прав("0000000"+СокрЛП(Константа.IDD),7)+прав("0000000000"+СокрЛП(Константа.УникальныйIDD),10);
ЗафиксироватьТранзакцию();
Возврат Рез;
КонецФункции
Итак, приступим. Будем использовать 1С++.
В глобальном модуле в процедуру ПриначалеРаботыСистемы() добавим следующие строки для создания таблицы и заполнения ее значениями:
//таблица IDD для МОДа
ТекстЗапроса = "
|if not exists (select name from dbo.sysobjects where name = 'UIDD' and xtype = 'U ')
|create table UIDD (idd char(7), uidd numeric(10,0))
|";
RecordSet.ВыполнитьИнструкцию(ТекстЗапроса);
//начальное заполнение значений таблицы
ТекстЗапроса = "
|if (select count(*) from UIDD (nolock)) = 0
|insert into UIDD values (:ИДД,:УникальныйИДД)
|";
RecordSet.УстановитьТекстовыйПараметр("ИДД", Константа.IDD);
RecordSet.УстановитьТекстовыйПараметр("УникальныйИДД", Число(Константа.УникальныйIDD));
RecordSet.ВыполнитьИнструкцию(ТекстЗапроса);
Теперь переделанный текст функции (спасибо за обсуждение на 1cpp.ru коллегам):
Функция ПолучитьНовыйИДД() Экспорт
ТекстЗапроса = "
|begin tran
|select right('0000000' + LTrim(idd), 7) + right('0000000000' + LTrim(str(uidd + 1, 10)),10)
|from UIDD (updlock)
|update UIDD
|set uidd = uidd + 1
|commit tran
|";
ТЗ = RecordSet.ВыполнитьИнструкцию(ТекстЗапроса);
Возврат ТЗ.ПолучитьЗначение(1,1);
КонецФункции
Слово Экспорт добавили не зря. В обработках конфигурации мы найдем изобилие конструкций с блокировкой константы, которые также нужно переделать
Пример переделанного кода:
Для ы=1 по Метаданные.Справочник() Цикл
НачатьТранзакцию();
//Блокировка=1;
//Пока Блокировка=1 Цикл
// Попытка
// НачатьТранзакцию();
// Константа.УникальныйIDD=Константа.УникальныйIDD;//блокируем
// Блокировка=0;//константа заблокирована не была - можем работать
// Исключение//константа заблокирована !!
// ОтменитьТранзакцию();
// //Ожидание для возможности работы других пользователей (по совету Олега Яковлева из ЧПТФ "ЮСИ")
// Стр=ТекущееВремя();
// Пока Стр=ТекущееВремя() Цикл
// КонецЦикла;
// КонецПопытки;
//КонецЦикла;
КолПрогрессора=КолПрогрессора+10;
Прогрессор(КолПрогрессора);//**************** прогрессор
Ст=Метаданные.Справочник(ы).Идентификатор;
Если (ст<>"ПравилаЗагрузки") и (ст<>"ПравилаВыгрузки") и (ст<>"ПериферийныеБазы") Тогда
Спр=СоздатьОбъект("Справочник."+Ст);
М_Состояние("Обработка "+Ст);
Спр.ВыбратьЭлементы(0);
Пока Спр.ПолучитьЭлемент()>0 Цикл
Если (Сокрлп(Спр.IDD)="")ИЛИ(ФлНовый=1) Тогда
//Константа_УникальныйIDD=Константа_УникальныйIDD+1;
//Спр.IDD=Сокрлп(Константа_IDD+прав("0000000000"+Константа_УникальныйIDD,10));
Спр.IDD = ПолучитьНовыйИДД();
Попытка
Спр.Записать();
Исключение
Сообщить("Ошибка на : "+Спр.Вид()+", владелец "+Спр.Владелец+", элемент="+Спр.ТекущийЭлемент()+", код="+Спр.Код+" . Внимание: найдите данный элемент справочника вручную и измените код !!");
КонецПопытки;
КонецЕсли;
Если РежимИниц=1 Тогда
ПриИзмененииОбъектаМОД(Спр,Спр,'01.01.1976',0);//для периодических реквизитов надо задавать период выгрузки
ПриИзмененииОбъектаМОД(Спр,Спр,РабочДата,0);//у нас период равен: 01.01.1976 - рабочая дата
КонецЕсли;
КонецЦикла;
КонецЕсли;
//Константа.УникальныйIDD=Строка(Число(Константа_УникальныйIDD)+1);
ЗафиксироватьТранзакцию();
КонецЦикла;
Не забывайте о том, что МОД при нахождении неуникальных IDD присваивает уникальные значения УЖЕ СУЩЕСТВУЮЩИМ объектам.
Начать дискуссию