Достаточно долгое время единственным уникальным ключом позиции в динамическом списке (далее ДС) являлась или ссылка, или конструкт вроде ключа записи регистра, чей состав и уникальность поддерживались платформой непрозрачно для разработчика. 1С сама транслировала ссылки и ключи в данные, однозначно идентифицирующие каждую подгружаемую, кэшируемую и выводимую строку динамического списка. Принципы подгрузки с сервера (при пролистывании, позиционировании, отборах), кэширования и обновления кэша, принципы показа и программного обращения - всё это было единообразно, но скрыто и нам недоступно.
Ситуация изменилась в релизе 8.3.14, где платформа стала поддерживать разные варианты ключей при работе с ДС, в т.ч. для произвольных запросов без основной таблицы. Это хорошо описано в Зазеркалье и на других ресурсах. Мы получили удобный инструмент решения коллизий дублирования ключевых полей, оптимизацию, прозрачность и управляемость (хотя бы фактом кэширования). Поведение системы в целом осталось тем же - контроль реальной уникальности ключа, каким бы он ни был, поддержка возможностей ДС, клиент-серверное взаимодействие и т.д., и при этом интерактивное добавление, удаление, открытие; т.е. то, что раньше было возможно лишь при наличии основной таблицы.
Тем не менее, есть нюансы поведения ДС при отсутствии основной таблицы и, тем более, с разными видами ключей.
Не весь функционал ДС с основной таблицей унаследован для ДС с произвольными запросами, даже для случаев, когда, казалось бы, построение ключа и поведение системы ровно то же. Так, "Уведомление не влияет на динамические списки, у которых не задана основная таблица" (с) СП, т.е. мы не можем рассчитывать на обновление ДС и очистку кэша форм выбора при вызове "ОповеститьОбИзменении" и при работе аналогичных стандартных команд. Приходится делать вручную, как и ранее.
Аналогично, "ОповеститьОбАктивизации", даже будучи вызван с корректным аргументом, эффекта не возымеет, поэтому для синхронизации ДС на произвольных запросах, даже с видом ключа "Авто", тоже всё вручную. Ряд релизов при связке справочников по владельцу средствами ДС без основной таблицы вообще аварийно завершался при чтении первой же порции данных.
Также, неработоспособен параметр формы "ТекущаяСтрока". Он автодобавляется при указании ДС, с любым видом ключа, как основного реквизита формы (что видно в подсказке при наборе кода), и поддерживает все возможные содержания при видах ключей, и передаётся, и читается программно, но свою основную задачу - позиционирование, особенно при открытии - не выполняет, игнорируется.
Есть особенности в поведении произвольных запросов с разными ключами, рассмотрим их на примере общеизвестных функций получения СКД и настроек ДС (например, описано тут). В качестве задачи возьмём, например, эмуляцию возможностей свойства "ТекущиеДанные" (доступного, в отличие от "ТекущаяСтрока", лишь на клиенте), на сервере.
Может указываться и для произвольного запроса без основной таблицы. При этом поле значения ключа сам не очищает и не проверяет.
Если указана основная таблица, то вид ключа "Авто", а поля ключа - пустой фиксированный массив. Вроде бы всё по умолчанию. Но при этом возможна ситуация, когда поле "Ссылка" есть в Наборе, в доступных к выбору и выбранных полях настройки СКД по умолчанию, и в Выбор текущей настройки СКД, но даже при плоской детализации структуры (взятой по умолчанию) его нет в результатной выборке-таблице. Во всех прочих вариантах ключей эффект не наблюдается, поле есть. От флага "ИспользоватьВсегда" этот эффект не зависит.
Если для произвольного запроса указана основная таблица, ПоляКлюча не то что бы недоступны, а именно "не используются" (с) СП. Замечено, что поведение при обращении к полям ключа может разниться для толстого и тонкого клиентов.
Вообще, "ПоляКлюча" согласно СП это "СписокПолей" (для ВводПоСтроке и ПоляКлюча внешних источников), но, в отличие от указанного в СП, т.е., цитирую, "В качестве полей ввода по строке могут выступать такие предопределенные реквизиты, как "Код", "Наименование", "Дата", "Номер" и реквизиты объектов, имеющие примитивный тип данных, для которых свойство объекта метаданных "Индексировать" принимает значение "Индексирование" или "Индексировать с доп. упорядочиванием"." - тут выбор доступных к указанию как поля ввода явно больше - и не только примитивные типы и предопределённые значения. Программно это подтверждается, поэтому и внимания к типизации полей СКД надо больше. Особенно, как всегда, аккуратнее с определяемыми типами, характеристиками, хранилищами, неогр.строками итд.
Даёт на выбор в значениях ключа всё, все поля выборки запроса, кроме "ВерсияДанных".
ПоляКлюча - фиксированный массив строк (всегда строго один элемент), где строки это имена полей (опять же, не следует применять разыменования от полей выборки "первого уровня", даже если конструктор ДС это скушал)
ТекущаяСтрока - текущее значение поля нужного типа.
Даёт на выбор вообще всё, любые поля. Явных ограничений ни по типам, ни по составу, ни по разыменованию нет. Но, полагаю, с разыменованиями тоже не следует связываться - опять же, любое поле "через точку" как неявное соединение с другими таблицами негативно скажется на производительности.
ПоляКлюча - фиксированный массив (возможны N элементов), каждый из элементов это строка с именем поля ключа.
ТекущаяСтрока - КлючСтрокиДинамическогоСписка - коллекция из "КлючИЗначение", причём значения - нужных типов и, если был многотипный, значение уже строго одного типа, типа реального наполнения.
Выбор настройки ПолеКлюча недоступен, в т.ч. программно; платформа нумерует строки выборки сама. Причём, как показали замеры, это делается на клиенте.
ПоляКлюча - пустой фикированный массив.
ТекущаяСтрока - число (нумерация с 1), причём это не свойство строки как объекта данных, это свойство текущей позиции исключительно при текущем сеансе показе (вывода порции данных на экран), т.е. сортировка по колонке и прочие манипуляции на идентификации не сказываются - всегда идёт по натуральному ряду, и под неким номером каждый раз могут оказываться разные строки выборки.
Для всех случаев ключей нельзя использовать поля, могущие иметь значения "Неопределено" и "Null", даже потенциально. Тут платформу одолевает паранойя даже при очевидных разыменованиях и составных типах. Многотипные, в общем случае, допустимы, в т.ч. смешанные из простых и ссылочных типов.
Если ДС сгруппирован, т.е. Группировки применены, то "ТекущаяСтрока" возвращает значение типа "СтрокаГруппировкиДинамическогоСписка", и её Ключ - значение ТекущиеДанные[ТекущаяКолонока] того поля группировки, где стоит активный курсор.
Защита от дублирования ключевых всегда срабатывает только при отображении ДС, а не при настройке, т.е. заранее не проверяется, что, при возможности программного переопределения, разумно.
Во всех режимах одинаково полные возможности Отбора, Порядка, Условного оформления. В режиме "НомерСтроки" отсутствует возможность Группировок; при этом возвращаемый ПолучитьОграниченияИспользованияВГруппировке() массив пуст.
Поведение самой СКД также имеет особенности. Для набора (типа "Набор запроса") стоит автозаполнение, но его Поля пусты, и поля Выбор и ДоступныеДляВыбора пусты; пусто и в СКД.НастройкиПоУмолчанию, и в основном варианте настройки. Актуальны и приоритетны именно исполняемые настройки: в Выборе пусто, а в Доступных для выбора - все нужные поля есть и корректно объявлены. Даже для вида ключа "Номер строки" в "ДоступныеПоляГруппировок" есть все поля выборки; в структуре запись детальной группировки (без групп.полей), в её выбранных - все поля выборки.
Если у ДС указаны в конфигураторе настройки, все они ровно так и отображается (отбор, порядок, группировка как структура), но искать их следует именно в исполняемых настройках, а не в НастройкиПоУмолчанию.
Получение ограничений использования (в отборе, в сортировке, в группировках) совершенно ничем не отличается от "Авто" и интереса не представляет.
Механизм автозаполнения доступных полей, механизм свойства "ПолучениеПредставленийДляНевидимыхПолей" (и соответственно кэш представлений ссылок формы) работают для всех случаев строго так же, как для обычных с основной таблицей.
И собственно функция, реализующая демонстрационную задачу
Важно: при программной работе со свойствами ДС интерпретатор платформы не проверяет правильность и взаимную связность настроек (это делает только интерфейс настройки ДС), т.е. например "ВидКлюча" не "Авто", и принудительно указывается свойство "ОсновнаяТаблица"; конфликт может вылезти только при исполнении - при первом обращении ДС к данным БД. В лучшем случае это будет ругательный MsgBox, в худшем - захват всей таблицы, которая основная, и повисание сеанса. Следует быть внимательным, а на релизах ниже 8.3.15 вообще лучше не трогать в коде эти свойства.
Открытым остаётся вопрос о порции считывания. При установленном флаге "Динамическое считывание данных" (доступном только при указанной основной таблице произвольного запроса, т.е. только в режиме "Авто") платформа читает от 45 до 70 записей таблицы (насколько я понял, в зависимости от постраничной разбивки читаемых таблиц СУБД). А вот различается ли размер порции при других видах ключей и кэшируются ли они промежуточно по внутренним ID либо перестраиваются и перечитываются каждый раз - тема отдельного исследования. Заявленный размер порции в 1000 записей на практике соблюдается не всегда, поэтому, по-хорошему, изучить бы надо и степень горячести запроса/прогретости кэша, и способ (курсор или через темпы), и тот же пейджинг, и всё это в связке с принципом построения итогового внутреннего хеш-ключа. Словом, простор для исследований.
Функция создавалась на релизе 8.3.16.1224