Как правильно работать с составными типами данных в регистрах сведений 1С и расширениях

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с регистрами сведений (РС) в системе 1С:Предприятие часто требует использования составных типов данных. Особенно остро вопросы архитектуры встают при разработке в расширениях конфигурации. В этой статье мы подробно проанализируем ситуацию, когда запись в регистр с составным типом ресурса или измерения ведет себя непредсказуемо, и разберем способы решения подобных проблем.

Понимание уникальности записей и структуры ключа

Прежде чем переходить к программному коду, разберем базовый принцип работы регистра сведений. Каждая запись в регистре должна быть уникальной. Уникальность определяется так называемым ключом записи. Рассмотрим, из чего он состоит:

  1. Для непериодического регистра: Ключ — это совокупность всех значений его измерений.
  2. Для периодического регистра: Ключ — это совокупность периода и всех значений измерений.

Если мы пытаемся записать данные в регистр, где значения измерений (и периода, если он есть) совпадают с уже существующей записью, система либо перезапишет старую запись, либо выдаст ошибку нарушения уникальности. В обсуждаемой ситуации автор столкнулся с тем, что запись второго типа документа "не создавалась". Это происходило потому, что при одинаковых измерениях система просто обновляла одну и ту же строку в базе данных, вместо создания новой.

Особенности использования Менеджера записи

В примере кода использовался объект СоздатьМенеджерЗаписи. Проанализируем его работу подробнее. Рассмотрим типичный фрагмент кода, который вызывает затруднения:


&НаСервере
Процедура СоздатьЗаписьВРегистре(Док, ОРП)
    ЗаписьСвязи = РегистрыСведений.Расш1_СвязиОРП.СоздатьМенеджерЗаписи();
    ЗаписьСвязи.Период = ТекущаяДата();
    ЗаписьСвязи.ГоловнойОтчет = ОРП;
    ЗаписьСвязи.ПодчиненныйРТУУСН = Док;
    ЗаписьСвязи.Записать(ЛОЖЬ);
КонецПроцедуры

В данном коде есть несколько критических моментов, которые мы разберем по шагам:

1. Параметр Замещать в методе Записать(). Метод Записать(ЛОЖЬ) указывает системе, что не нужно замещать существующую запись. Если в регистре уже есть запись с таким же ключом (те же измерения и период), система выдаст ошибку "Запись с такими ключевыми полями существует". Чтобы разрешить перезапись данных, следует использовать Записать(ИСТИНА) или просто Записать(), так как по умолчанию параметр установлен в ИСТИНА.

2. Чтение перед записью. Менеджер записи при вызове Записать() сначала пытается найти запись по ключевым полям. Если вы работаете с составным типом в измерениях, крайне важно, чтобы все части ключа были заполнены корректно. Если одно из измерений имеет составной тип и туда передается неверный тип ссылки, менеджер может "промахнуться" мимо существующей записи.

Составной тип: Измерение или Ресурс?

Проанализируем разницу в поведении системы в зависимости от того, где расположен составной тип данных:

  1. В измерениях: Если поле ПодчиненныйРТУУСН является измерением, то записи с разными ссылками (разными документами) будут считаться разными ключами. В этом случае в регистре могут одновременно существовать записи для "Реализации" и для "Возврата" при одном и том же ГоловномОтчете.
  2. В ресурсах: Если ПодчиненныйРТУУСН — это ресурс, то для одного ГоловногоОтчета (измерения) может существовать только одна запись. При записи "Возврата" данные о "Реализации" будут просто стерты и заменены новыми.

Выясним причину проблемы автора: он пытался хранить разные типы документов для одного головного объекта, но поле было ресурсом или измерения были определены некорректно. Перенос поля из ресурсов в измерения или включение периодичности (как сделал автор, установив период "до секунды") позволяет физически разделить эти записи в базе данных.

Использование Определяемых типов в расширениях

Для работы с составными типами в 1С рекомендуется использовать ОпределяемыйТип. Это упрощает поддержку кода. Однако в контексте расширений есть нюансы:

Программная запись через Набор записей

Если нам нужно гарантированно записать данные, особенно при работе с составными типами, зачастую эффективнее использовать НаборЗаписей вместо МенеджераЗаписи. Разберем, как это реализовать:


Набор = РегистрыСведений.Расш1_СвязиОРП.СоздатьНаборЗаписей();
Набор.Отбор.ГоловнойОтчет.Установить(ОРП);
// Если регистр периодический, можно установить отбор по периоду
// Набор.Отбор.Период.Установить(ТекущаяДата);

НоваяЗапись = Набор.Добавить();
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.ГоловнойОтчет = ОРП;
НоваяЗапись.ПодчиненныйРТУУСН = Док;

Набор.Записать(ЛОЖЬ); // ЛОЖЬ означает, что мы не затираем записи по данному отбору, а добавляем к ним (если позволяет уникальность)

Использование НабораЗаписей с установленным фильтром (отбором) работает стабильнее при массовой обработке данных и позволяет четко контролировать, какие именно записи будут изменены.

Важные рекомендации по работе с составными типами в БД

Посмотрим на ситуацию с точки зрения производительности SQL-сервера. Когда мы используем составной тип в измерениях регистра сведений, 1С создает в таблице базы данных несколько колонок для одного поля (отдельно для типа и отдельно для ссылки). Это приводит к следующим последствиям:

Итоги решения проблемы

Для исправления ошибок записи составных типов в регистры сведений расширения мы рекомендуем следующий алгоритм действий:

  1. Проверить, являются ли поля с составным типом измерениями. Если нужно хранить несколько разных документов для одного владельца, эти документы должны входить в ключ записи.
  2. Определиться с периодичностью. Если в одну секунду может быть создано несколько связей, возможно, стоит пересмотреть структуру измерений, чтобы обеспечить уникальность без привязки ко времени.
  3. Использовать метод Записать(ИСТИНА) для менеджера записи, чтобы избежать ошибок блокировки и дублирования ключа при обновлении данных.
  4. В расширениях внимательно следить за тем, чтобы все типы, входящие в составной тип, были заимствованы или созданы в этом же расширении.

Следуя этим правилам, мы обеспечим целостность данных в регистрах сведений и корректную работу механизмов расширения конфигурации.

← На главную