При интеграции 1С с внешними системами (например, при периодической загрузке логов через ADODB) разработчики часто сталкиваются с ситуацией, когда повторный запуск процедуры либо полностью очищает существующие записи в регистре сведений, либо дублирует их. Рассмотрим причины этого поведения и проанализируем решения этой задачи.
Разберем стандартный алгоритм работы с объектом РегистрСведенийНаборЗаписей. Когда мы создаем новый набор записей с помощью метода СоздатьНаборЗаписей(), он изначально пуст и не содержит никаких отборов.
Посмотрим на типичный фрагмент кода, приводящий к полной перезаписи регистра:
&НаСервере
Процедура ДобавлениеЗаписиВРегистр(ТЗ)
НаборЗаписей = РегистрыСведений.ЛогиТМГ.СоздатьНаборЗаписей();
Для Каждого Строка Из ТЗ Цикл
Запись = НаборЗаписей.Добавить();
ЗаполнитьЗначенияСвойств(Запись, Строка);
КонецЦикла;
// Вызов метода Записать() по умолчанию использует параметр Замещать = Истина
НаборЗаписей.Записать();
КонецПроцедуры
Метод Записать() объекта РегистрСведенийНаборЗаписей принимает булевый параметр Замещать, значение которого по умолчанию равно Истина. Если у набора записей независимого регистра сведений не установлен отбор по измерениям, вызов Записать() полностью стирает все данные в регистре и записывает только те строки, которые находятся в текущем наборе в данный момент.
Важно: В независимом регистре сведений отбор в наборе записей можно установить только по измерениям. Установить отбор по ресурсам или реквизитам платформой 1С запрещено.
Чтобы добавить новые данные к уже существующим без предварительной очистки регистра, следует явно передать значение Ложь в метод Записать():
&НаСервере
Процедура ДобавитьНовыеЗаписи(ТЗ)
НаборЗаписей = РегистрыСведений.ЛогиТМГ.СоздатьНаборЗаписей();
Для Каждого Строка Из ТЗ Цикл
Запись = НаборЗаписей.Добавить();
ЗаполнитьЗначенияСвойств(Запись, Строка);
КонецЦикла;
// Режим добавления записей без перезаписи регистра
НаборЗаписей.Записать(Ложь);
КонецПроцедуры
При вызове НаборЗаписей.Записать(Ложь) платформа попытается добавить новые строки к имеющимся в базе данных. Однако здесь необходимо учитывать ключевое правило платформы 1С:
Уникальность строк в регистре сведений определяется строго комбинацией значений его измерений (и периода, если регистр периодический). Если вы передадите запись, комбинация измерений которой уже существует в базе, платформа вызовет ошибку необрабатываемого исключения (нарушение уникальности данных).
Для корректной работы этого метода убедимся, что ключевые параметры лога (например, дата/время события, имя сервера, порядковый номер) назначены именно Измерениями регистра, а не ресурсами.
Если требуется проверять существование каждой конкретной записи перед сохранением, удобнее использовать Менеджер записи. Посмотрим, как реализовать этот подход пошагово:
СоздатьМенеджерЗаписи() для соответствующего регистра.Прочитать().Выбран(). Если метод возвращает Ложь, значит, такой записи в базе еще нет — заполняем остаток полей и вызываем Записать().Проанализируем пример кода:
&НаСервере
Процедура ЗаписатьЧерезМенеджер(ТЗ)
Для Каждого Строка Из ТЗ Цикл
МенеджерЗаписи = РегистрыСведений.ЛогиТМГ.СоздатьМенеджерЗаписи();
// Указываем значения измерений для поиска
МенеджерЗаписи.GMTlog = Строка.GMTlog;
МенеджерЗаписи.SrvName = Строка.SrvName;
МенеджерЗаписи.NUM = Строка.NUM;
// Пытаемся прочитать существующую запись
МенеджерЗаписи.Прочитать();
// Записываем только если запись не была найдена
Если НЕ МенеджерЗаписи.Выбран() Тогда
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Строка);
МенеджерЗаписи.Записать();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Загрузка полного объема логов во временную таблицу значений при каждом запуске обработки создает значительную нагрузку на оперативную память и снижает быстродействие системы. Чтобы оптимизировать процесс, применим фильтрацию еще на этапе запроса к внешней СУБД:
WHERE GmtLogTime > @LastLoadedTime).