Работа с современными конфигурациями на платформе 1С, такими как Управление торговлей 11.5, ERP 2 или Комплексная автоматизация 2, требует от разработчика особого внимания к механизмам записи объектов. Обычный вызов метода Записать(), который корректно работал в старых версиях программ (например, УТ 10.3), в новых реализациях может привести к катастрофическим последствиям: порче данных, потере единиц измерения и взрывному росту объема базы данных SQL.
В этой статье мы подробно проанализируем ситуацию, когда после программного обновления артикулов номенклатуры база выросла в два раза, а единицы хранения (кг, пачки, короба) самопроизвольно изменились на «штуки». Выясним причины этого «коллапса» и разберем правильный алгоритм массового изменения данных.
Рассмотрим типичную ситуацию. Разработчику необходимо программно заполнить поле Артикул для всех позиций номенклатуры, используя код объекта. На первый взгляд, задача тривиальна. Разберем пример кода, который часто используют новички (и который приводит к проблемам):
Процедура Команда1НаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ
| И Номенклатура.Артикул = &пАрт";
Запрос.УстановитьПараметр("пАрт", "");
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
пОбъект = Выборка.Ссылка.ПолучитьОбъект();
пОбъект.Артикул = "АВТ" + СокрЛП(пОбъект.Код);
пОбъект.Записать(); // Здесь кроется главная ошибка
КонецЦикла;
КонецПроцедуры
На первый взгляд, код логичен. Мы выбираем номенклатуру с пустым артикулом, формируем новое значение и записываем объект. Однако при выполнении этого кода в УТ 11.5 начинают происходить необъяснимые вещи. Разберем пошагово, почему это происходит.
В конфигурации 1С:Управление торговлей 11.5 логика работы с единицами измерения (упаковками) значительно усложнена. Проблема «слета» единиц измерения при простой записи объекта связана с работой внутренних обработчиков событий:
Записать() система запускает процедуры ПередЗаписью и ПриЗаписи. В типовых решениях в эти моменты проверяется целостность структуры данных. Если система обнаруживает изменение ключевых реквизитов или просто выполняет проверку по умолчанию, она может инициировать перезаполнение зависимых параметров.Увеличение размера бэкапа с 6 ГБ до 12 ГБ после простой перезаписи справочника — это не ошибка SQL, а штатное поведение системы при определенных настройках. Выделим три основных фактора роста:
Номенклатура. При каждом вызове метода Записать() система создает полную копию данных объекта в регистре сведений ВерсииОбъектов. Номенклатура в УТ 11 — это «тяжелый» объект с десятками реквизитов и табличных частей. Перезаписав 10 000 позиций, вы фактически создаете еще 10 000 их полных копий в базе.НоменклатураПоставляемаяПоставщиками). Это вызывает рост LDF-файла (лога транзакций) в SQL Server.Для предотвращения выполнения лишней бизнес-логики, проверок и срабатывания подписок на события при программном изменении данных, критически важно использовать свойство ОбменДанными.Загрузка. Это сообщает системе, что объект записывается в режиме «как есть», и никакие дополнительные проверки или изменения зависимых реквизитов (например, единиц измерения) производиться не должны.
Рассмотрим исправленный и безопасный вариант кода:
Процедура Команда1НаСервереБезопасно()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
пОбъект = Выборка.Ссылка.ПолучитьОбъект();
пОбъект.Артикул = "АВТ" + СокрЛП(пОбъект.Код);
// КЛЮЧЕВАЯ СТРОКА: отключение бизнес-логики
пОбъект.ОбменДанными.Загрузка = Истина;
пОбъект.Записать();
КонецЦикла;
КонецПроцедуры
Что дает использование этого флага:
Если вы уже столкнулись с ростом базы и порчей данных, выполните следующие шаги для восстановления:
Если данные в регистрах накопления уже «поплыли», простой замены «шт.» на «кг» в справочнике может быть недостаточно. Проанализируйте регистр ШтрихкодыНоменклатуры и УпаковкиНоменклатуры. Возможно, потребуется написать корректирующую обработку, которая сопоставит старые значения единиц (из бэкапа или логов) и вернет их программно с флагом ОбменДанными.Загрузка = Истина.
Чтобы вернуть объем базы к прежним значениям, проанализируйте регистр ВерсииОбъектов. В типовых конфигурациях есть стандартная обработка «Очистка ненужных версий» (раздел Администрирование — Поддержка и обслуживание). Удалите версии, созданные во время выполнения вашей неудачной обработки.
После удаления лишних записей из регистра версий физический размер файла базы данных SQL не уменьшится автоматически. Вам потребуется выполнить процедуру Shrink (сжатие) для базы данных в консоли SQL Server Management Studio, чтобы освободить неиспользуемое место на диске.
Если размер базы вырос из-за журнала регистрации, рассмотрите возможность его сокращения. В режиме 1С:Предприятие это делается через «Администрирование — Поддержка и обслуживание — Журнал регистрации — Сократить».
Массовая программная обработка справочников в 1С:УТ 11.5 — это ответственная операция. Никогда не используйте метод Записать() «в лоб» без предварительного анализа подписок на события и настройки ОбменДанными.Загрузка. Помните, что современные конфигурации живут по сложным законам объектной модели, где изменение одного реквизита может по цепочке изменить всю структуру данных товара.