08.10.2010
Не во всех ситуациях динамический список может корректно отобразить данные, полученные из произвольного запроса. Поэтому задача разработчика заключается в том, чтобы правильно использовать возможности, предоставляемые динамическим списком. Рассмотрим одну из типичных ситуаций.
Существует справочник Товары и документ Накладная, который регистрирует поступление товаров. В каждой накладной указывается, от какого поставщика получены товары.
Для удобства пользователей решено показывать в списке товаров еще и поставщика, от которого получен этот товар. Для этого динамический список товаров использует произвольный запрос следующего вида:
Таблица справочника Товары связывается с табличной частью документа Накладная и из таблицы документа выбирается поставщик, от которого получен этот товар.
В качестве основной таблицы динамического списка указана таблица Справочник.Товары. Таким образом, считывание данных будет выполняться порциями динамически. Чтобы обеспечить правильность курсора, считывающего данные, динамический список добавит в запрос сортировку по полям Наименование и Ссылка из основной таблицы Справочник.Товары.
Оба упомянутых поля уже есть в запросе, поэтому динамический список добавляет только раздел УПОРЯДОЧИТЬ ПО. В результате запрос получается таким:
Копировать в буфер обменаВЫБРАТЬ СправочникТовары.Ссылка КАК Ссылка, СправочникТовары.ПометкаУдаления, СправочникТовары.Предопределенный, СправочникТовары.Код, СправочникТовары.Наименование КАК Наименование, НакладнаяТовары.Ссылка.Поставщик ИЗ Справочник.Товары КАК СправочникТовары ЛЕВОЕ СОЕДИНЕНИЕ Документ.Накладная.Товары КАК НакладнаяТовары ПО (НакладнаяТовары.Товар = СправочникТовары.Ссылка) УПОРЯДОЧИТЬ ПО СправочникТовары.Наименование, СправочникТовары.Ссылка
Теперь посмотрим на запрос. В запросе указано левое соединение основной таблицы справочника Товары с табличной частью документа Накладная. Это значит, что для каждой строки из основной таблицы будет выведено ее объединение с каждой строкой из табличной части, удовлетворяющее условию ПО.
В системе существует два товара и проведено две накладных, которыми оформлено поступление этих товаров.
Таким образом, в процессе выполнения этого запроса, для товара Молоко будет найдена одна подходящая запись:
А для товара Хлеб будет найдена тоже одна подходящая запись:
В результате данные, предназначенные для отображения динамическим списком, будут выглядеть следующим образом:
Список номенклатуры |
||
---|---|---|
Ссылка |
Наименование |
Поставщик |
0acffba3-d075-47d4-9e0a-0b4784733e55 |
Молоко |
Молокозавод |
7ebac629-5da1-4ab0-975d-bf245208de03 |
Хлеб |
Пекарня |
В этом случае динамический список работает полностью корректно:
Теперь представим, что поставщик Хлебокомбинат тоже поставил нам хлеб. В результате в табличной части документа Накладная окажется уже две записи, удовлетворяющие условию левого соединения:
В результате данные, предназначенные для отображения динамическим списком, будут выглядеть следующим образом:
Список номенклатуры |
||
---|---|---|
Ссылка |
Наименование |
Поставщик |
0acffba3-d075-47d4-9e0a-0b4784733e55 |
Молоко |
Молокозавод |
7ebac629-5da1-4ab0-975d-bf245208de03 |
Хлеб |
Пекарня |
7ebac629-5da1-4ab0-975d-bf245208de03 |
Хлеб |
Хлебокомбинат |
Таким образом, оказывается, что для двух записей дублируются значения полей, по которым динамический список выполняет сортировку для правильной работы курсора, считывающего данные:
Копировать в буфер обмена... УПОРЯДОЧИТЬ ПО СправочникТовары.Наименование, СправочникТовары.Ссылка
В результате список начинает отображать данные неправильно, т.к. дублируются значения в ключевых полях.
Приведенный пример показывает наиболее частую причину неправильной работы динамического списка. Из него следует следующее правило: если указана основная таблица динамического списка, то количество записей, получаемых в результате, не должно превышать количество записей, извлекаемых из таблицы, которая указана в качестве основной для динамического списка.
Если же в результате выполнения запроса количество строк, получаемых запросом из основной таблицы, увеличивается, это будет приводить к тому, что начнут дублироваться ключи этих строк, т.к. ключ строится именно по полям основной таблицы. В результате список может работать некорректно.
Избавиться от этого, не меняя запрос можно, убрав указание основной таблицы. При этом запрос становится полностью статическим и для каждой строки выборки генерируется суррогатный ключ - простое число.
Список номенклатуры |
|||
---|---|---|---|
Ссылка |
Наименование |
Поставщик |
Ключ |
0acffba3-d075-47d4-9e0a-0b4784733e55 |
Молоко |
Молокозавод |
1 |
7ebac629-5da1-4ab0-975d-bf245208de03 |
Хлеб |
Пекарня |
2 |
7ebac629-5da1-4ab0-975d-bf245208de03 |
Хлеб |
Хлебокомбинат |
3 |
Суррогатный ключ обеспечивает уникальную идентификацию строк для динамического списка, что обеспечивает его правильную работу.
Однако в этом случае пропадают некоторые интерактивные возможности. Например, не будет возможности добавлять в список новые элементы, т.к. неизвестно, что содержит список. Пока была указана основная таблица Справочник.Товары, платформа знала, что добавлять нужно элементы справочника Товары. Когда основная таблица не указана, платформа такой информации не имеет.