Запись данных в регистр сведений — одна из базовых и наиболее часто встречающихся задач при разработке в среде 1С:Предприятие. Несмотря на кажущуюся простоту, начинающие разработчики часто сталкиваются с ситуацией, когда код выполняется без ошибок, но в пользовательском режиме новые записи так и не появляются. В этой статье мы подробно разберем, почему это происходит, проанализируем типичные ошибки и рассмотрим наиболее эффективные, современные и безопасные методы работы с регистрами сведений.
Прежде чем переходить к написанию кода, давайте разберем причины, по которым внесенные изменения могут остаться незамеченными в интерфейсе программы:
"20190421" вместо полноценного типа данных Дата заставляет платформу принудительно выполнять приведение типов. Если такое преобразование завершается неудачей на уровне СУБД, запись может не создаться или создаться с пустой датой, из-за чего она "улетает" в самое начало списка.Теперь рассмотрим два основных подхода к программной записи в регистры сведений: использование набора записей и использование менеджера записи.
Этот метод является классическим и универсальным. Набор записей представляет собой коллекцию строк, отобранных по определенным правилам. Данный способ незаменим, когда требуется записать сразу несколько строк или когда мы работаем с регистрами, подчиненными регистратору.
Рассмотрим правильный и безопасный шаблон кода для работы с набором записей:
// Создаем объект Набор Записей для конкретного регистра
НаборЗаписей = РегистрыСведений.КурсВалют.СоздатьНаборЗаписей();
// Находим необходимую валюту в справочнике
Доллар = Справочники.Валюты.НайтиПоНаименованию("Доллар");
// Устанавливаем жесткий отбор по ключевым измерениям.
// Это критически важно, чтобы не затереть лишние данные в базе!
НаборЗаписей.Отбор.Валюта.Установить(Доллар);
НаборЗаписей.Отбор.Период.Установить('20190421');
// Читаем существующие записи из базы по установленным отборам
НаборЗаписей.Прочитать();
// Проверяем, есть ли уже такая запись в базе данных
Если НаборЗаписей.Количество() = 0 Тогда
// Если записи нет — добавляем новую строку в коллекцию
НовЗапись = НаборЗаписей.Добавить();
НовЗапись.Период = '20190421';
НовЗапись.Валюта = Доллар;
Иначе
// Если запись существует — берем ее для редактирования
НовЗапись = НаборЗаписей[0];
КонецЕсли;
// Заполняем ресурсы и реквизиты записи
НовЗапись.Курс = 57;
НовЗапись.Кратность = 1;
// Записываем набор в базу данных с включенным замещением
НаборЗаписей.Записать(Истина);
Внимание! Смертельная опасность параметра "Замещать"!
В методе НаборЗаписей.Записать(Истина) параметр Истина указывает платформе на необходимость замещения. Система находит в базе абсолютно все записи, соответствующие установленным в объекте Отбор значениям, удаляет их и вставляет новые записи из текущего набора.
Запомните правило: если вы забудете установить отборы в наборе записей и вызовете Записать(Истина) для пустого набора, система бесследно удалит абсолютно все записи из этого регистра сведений!
Если перед вами стоит задача создать, прочитать или обновить всего одну конкретную строку в независимом регистре сведений, использование набора записей является избыточным. Для этих целей гораздо проще и безопаснее применять специальный объект — РегистрСведенийМенеджерЗаписи.
Менеджер записи работает по принципу объектной модели (подобно документу или элементу справочника). Рассмотрим, как выглядит аналогичная процедура записи с его помощью:
// Создаем объект менеджера записи для независимого регистра
МенеджерЗаписи = РегистрыСведений.КурсВалют.СоздатьМенеджерЗаписи();
Доллар = Справочники.Валюты.НайтиПоНаименованию("Доллар");
// Заполняем ключевые поля (измерения и период), по которым будет выполняться поиск
МенеджерЗаписи.Период = '20190421';
МенеджерЗаписи.Валюта = Доллар;
// Пытаемся прочитать существующую запись из базы данных
МенеджерЗаписи.Прочитать();
// Независимо от того, была ли найдена запись, заполняем/обновляем ресурсы
МенеджерЗаписи.Курс = 57;
МенеджерЗаписи.Кратность = 1;
// Физически записываем изменения в базу данных.
// Платформа сама поймет, нужно ли сделать INSERT или UPDATE.
МенеджерЗаписи.Записать(Истина);
Использование менеджера записи полностью страхует вас от случайной очистки регистра сведений, поскольку в нем нет механизма коллективного отбора, способного удалить незадействованные строки.
Выясним причину споров разработчиков на форуме касательно формата даты. В коде автора из примера фигурирует конструкция "20190421". Это обычная текстовая строка. Написание даты в таком формате является грубой архитектурной ошибкой.
Для корректной работы платформы и СУБД используйте только явные способы представления даты:
'20190421' или '2019-04-21'. В этом случае 1С сразу на этапе компиляции понимает, что имеет дело с типом Дата.Дата(2019, 4, 21). Этот метод также полностью исключает неявные преобразования типов и гарантирует стабильную работу кода независимо от региональных настроек сервера.Перед написанием кода обязательно проверьте свойства вашего регистра в конфигураторе:
Движения или с установкой обязательного отбора по регистратору:
НаборЗаписей = РегистрыСведений.РегистрПодчиненный.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Регистратор = СсылкаНаДокумент;
// Заполнение остальных полей...
НаборЗаписей.Записать();
Если вы работаете в высоконагруженных системах или используете платформу версии 8.3.26 и выше, обратите внимание на новые стандарты производительности при записи регистров:
Удаление, а в 8.3.27 — режимы Обновление и Слияние. Это позволяет точечно вносить изменения на уровне базы данных.
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.КурсВалют");
ЭлементБлокировки.УстановитьЗначение("Валюта", Доллар);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Соблюдение этих простых правил не только убережет вас от трудноуловимых ошибок и случайной потери данных, но и обеспечит высокую скорость работы вашей конфигурации даже при значительном увеличении объема информационной базы.