Объектная модель запроса "Схема запроса" 2

06.12.23

Разработка - Запросы

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

Мне лично очень нравится статья - //infostart.ru/1c/articles/307045/

Также я использовал принципы из библиотеки тестирования YAXUNIT

В комментариях к оригиналу - возникли обоснованные сомнения в рациональности использования объектной схемы запроса, я надеюсь не создавать повод для очередных споров, а попытаться создать более "Юзабельный" пример.

Также прикладываю "упрощенный" граф "Схемы запроса" - сомневаюсь, что им действительно можно, или нужно пользоваться (кажется,  намного проще представлять в голове знакомый всем запрос 1С, разбитый на "блоки" соответствующие той или иной процедуре СхемыЗапроса), так что, он тут скорее для красивой картинки.

Не претендую на то, что мое решение лучшее из возможных, руководствуюсь общей идеей о том, что если мы хотим, чтобы будущее было светлым - следует попробовать улучшить что-то. Возможно, вам понравится мое решение, возможно, даст вам пищу для размышления или вдохновение для собственных решений.

Мне понадобятся 2 общих модуля, создающих более удобную "обертку" вокруг типовых функций построения схемы запроса.

1. Общий модуль - ТекучийКод - Серверный, ПовторноеИспользование - на время сеанса.
(Совсем простенький, чтобы сохранять текущий контекст)

Функция Контекст(Строка_УИД) Экспорт
	Возврат Новый Структура();
КонецФункции

2. Общий модуль - ОбъектЗапрос - Серверный.
(Обертка, реализующая текучий интерфейс. Он посложнее, однако вникать имеет смысл, только если вы хотите разобраться в принципах самого механизма объектных запросов, можно просто скопировать.)

 
 Общий модуль ОбъектЗапрос

Попробуем воссоздать запрос из оригинальной статьи, используя меньше кода. Поскольку использование механизма я вижу скорее в модификации существующих запросов, точка входа - минимальный запрос, который мы "дособерем" в процессе:

ТестЗапрос = Новый Запрос;
ТестЗапрос.Текст = 
"ВЫБРАТЬ
|	Товары.Ссылка КАК Номенклатура
|ИЗ
|	Справочник.Номенклатура КАК Товары";

ОбъектЗапрос.СхемаЗапроса(ТестЗапрос)
	.Пакет(0).Выборка(0)
	.Разрешенные()
	.ДобавитьЛевоеСоединение("Товары", "РегистрНакопления.Закупки.Обороты", "Закупки", "Закупки.Номенклатура = Товары.Ссылка")
	.УстановитьПараметрыОбороты("&Начало", "&Окончание", "Месяц")
		.ДобавитьПоле("Закупки.Период", "Период")
		.ДобавитьПоле("ЕСТЬNULL(Закупки.СуммаОборот, 0)", "СуммаЗакупок")
		.ДобавитьПоле("0", "СуммаПродаж")
		.Поместить("ТаблицаОбороты")
		.ДобавитьГде("НЕ Товары.ЭтоГруппа")
		
	.ДобавитьОбъединение("Справочник.Номенклатура", "Товары")
		.Различные().Первые(100)                                        
	.ДобавитьЛевоеСоединение("Товары", "РегистрНакопления.Продажи.Обороты", "Продажи", "Продажи.Номенклатура = Товары.Ссылка")
	.УстановитьПараметрыОбороты("&Начало", "&Окончание", "Месяц")  
		.ДобавитьПоле("Товары.Ссылка", "Номенклатура") // Объединяется по псевдониму
		.ДобавитьПоле("Продажи.Период", "Период")
		.ДобавитьПоле("0", "СуммаЗакупок")
		.ДобавитьПоле("ЕСТЬNULL(Продажи.СуммаОборот, 0)", "СуммаПродаж")
		.ДобавитьГде("НЕ Товары.ЭтоГруппа")
	    .Индекс("Номенклатура, Период")          
		
	.ДобавитьПакет("ТаблицаОбороты", "ТаблицаОбороты")
		.ДобавитьПоле("ТаблицаОбороты.Номенклатура", "Номенклатура")
		.ДобавитьПоле("ТаблицаОбороты.Период", 		 "Период")
		.ДобавитьПоле("СУММА(ТаблицаОбороты.СуммаЗакупок)", "СуммаЗакупок")
		.ДобавитьПоле("СУММА(ТаблицаОбороты.СуммаПродаж)", "СуммаПродаж")
		.Группировка("ТаблицаОбороты.Номенклатура, ТаблицаОбороты.Период")
		.ДобавитьГде("СУММА(ТаблицаОбороты.СуммаЗакупок) > 0") // Говорят схема запроса сама определит раздел "ИМЕЮЩИЕ"? 
		.Порядок("Номенклатура, Период")
		.ИтогиОбщие()
		.ИтогиПо("2, 3")
		.ИтогТолькоИерархия("Номенклатура")
	.Уничтожить("ТаблицаОбороты")
.Завершить();

Обратите внимание, что форматирование отступов - произвольное, я оформил так, как удобнее читать лично мне, надеюсь и вам тоже.

Идеи для улучшения:

В данный момент селекторы реализованы через индексы, в случае с большими запросами - это может быть не слишком удобно. Кажется, лучше было бы реализовать поиск по псевдонимам, это должно быть более читаемо, когда мы будем анализировать код изменяющий запрос. Нам ведь важно, что именно изменилось? Сравните варианты:

Выборка(0).ДобавитьПоле("Закупки.Период", "Период") 

Выборка("Товары").ДобавитьПоле("Закупки.Период", "Период")

Да и в целом код, наверное, можно еще причесать, у меня, к сожалению, нет много времени на это, надо работать :) 

Надеюсь, что это станет хорошей "точкой отсчета", если вы захотите использовать этот функционал.

запрос объектная модель запроса модификация запроса текучий интерфейс

См. также

SALE! %

Инструментарий разработчика Роли и права Запросы СКД Программист Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

12000 10000 руб.

02.09.2020    161465    893    399    

873

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    10298    sergey279    18    

64

Запросы Программист Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    5495    XilDen    36    

81

Запросы Программист Запросы Бесплатно (free)

Отлаживая взаимодействие с базой данных, мы регулярно сталкиваемся с зависающими или подозрительно долго выполняющимися обращениями, негативно влияющими на производительность. О том, как в PostgreSQL выявить подозрительные запросы, основываясь на доступной о них информации, расскажем в статье.

16.08.2024    8179    user1840182    5    

28

Математика и алгоритмы Запросы Программист Платформа 1С v8.3 Запросы Бесплатно (free)

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2488    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

Часто при разработке отчетов в СКД возникает ситуация, когда не совсем понятно, почему отчет выводит не те данные, которые нужны, либо не выводит вовсе. Возникает потребность увидеть конечный запрос, который формирует СКД. Как это сделать, рассмотрим в этой статье.

15.05.2024    9096    implecs_team    6    

47

Запросы Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3454    andrey_sag    10    

36
Отзывы
25. Alxby 1116 27.02.24 09:24 Сейчас в теме
(24)К сожалению, значение в кэше модуля повторного использования может быть удалено в не только в этом случае. ИТС: "... Кроме этого значение будет удалено при нехватке оперативной памяти в рабочем процессе сервера, при перезапуске рабочего процесса и при переключении клиента на другой рабочий процесс....". Вообще говоря, использовать переопределяемый модуль для хранения значения - это не то, для чего этот механизм предназначен. Для целей статьи гораздо проще и надежнее хранить контекст в переменной и передавать его в качестве параметра во все функции.
user1923546; +1 Ответить
Остальные комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. infosoft-v 930 06.12.23 09:40 Сейчас в теме
Отличная статья, спасибо.
Ссылка указанная в начале статьи не работает
10. Неопределено 91 07.12.23 06:27 Сейчас в теме
2. frkbvfnjh 805 06.12.23 10:07 Сейчас в теме
Очень интересные подходы :) Возвращать объект общего модуля для краткости записи и использования собственного "диалекта" синтаксиса и хранить контекст используя механизм повторного использования. Огонь! Только модуль наверное должен называться ТекущийКод, а не ТекучийКод, или он все таки текучий?
9. German 413 07.12.23 05:49 Сейчас в теме
(2) Необычный подход. Вот только работать будет в моменте для 1 сеанса
user1923546; +1 Ответить
16. user1923546 50 07.12.23 12:21 Сейчас в теме
(9) Вот про это, можно поподробнее? Тут есть проблема которую я не понимаю?
Сеанс ведь существует в любом случае, даже для регламентного задания... а при вызове ОбъектЗапрос.СхемаЗапроса(ТестЗапрос) - контекст очищается...

Вы предполагаете, что повторное использование на время сеанса - не изолирует получение контекста между сеансами?
То есть... ТекучийКод.Контекст("ОбъектныеЗапросы") - вызванный "одновременно" из разных сеансов может вызвать сбой?
Я предполагал, что разные сеансы получат разные структуры... если это не так, то для получения контекста следует использовать конструкцию вроде...?

ТекучийКод.Контекст("ОбъектныеЗапросы"+НомерСоединенияИнформационнойБазы());


Меня немного смущает, что такой вариант, вероятно, будет создавать мусор, но структуру контекста можно очищать при вызове функции Завершить() - я предполагаю, что если кто-то начал модифицировать запрос, то он хочет получить результат, а значит вызовет эту функцию непременно.
20. German 413 08.12.23 06:49 Сейчас в теме
(16) Это я затупил что то, изолирует конечно
3. brr 184 06.12.23 10:58 Сейчас в теме
.Пакет(0).Выборка(0)
вот тут было бы не плохо имена задавать, а не индекс. А уже в самом контексте хранить связи между именем и индексом.
4. ImHunter 328 06.12.23 11:46 Сейчас в теме
(2) Текучий:) Fluent, иначе.
(0) Поплюсую... Еще бы пример с модификацией на убирание или замену каких-то составляющих запроса.
6. frkbvfnjh 805 06.12.23 14:20 Сейчас в теме
(4) Да, все таки это Fluent...
5. maksa2005 551 06.12.23 12:27 Сейчас в теме
Мне лично очень нравится статья - //infostart.ru/1c/articles/307045/

не корректная ссылка
7. naf2000 06.12.23 18:01 Сейчас в теме
Linq при помощи синей изоленты
so-quest; +1 Ответить
8. DrZombi 301 06.12.23 18:05 Сейчас в теме
Очень интересно, но ни черта не понял.
Запрос может состоять из многих запросов, чет не нашел об этом упоминания :)


Короче в вашей статье примера кода есть море ограничений в использовании, вы об этом не стали упоминать...

Пишите еще, тема си...ек не развернута...
11. dhurricane 07.12.23 10:26 Сейчас в теме
Лично для меня тема объектной модели запроса по-прежнему остается актуальной. Увидев заголовок статьи сперва обрадовался - очень надеялся, что под капотом Вашей разработки не используется платформенная СхемаЗапроса... но нет, используется. Жаль.
12. dhurricane 07.12.23 10:29 Сейчас в теме
Не хватает "текучести" в описании соединения, на мой взгляд. Удобнее было бы описывать условия соединения отдельными методами построчно, а не одним большим текстом со всеми условиями.
13. user1923546 50 07.12.23 12:08 Сейчас в теме
(12) Да, описание соединения, мне тоже показалось громоздким, особенно на общем фоне... Однако все его элементы должны быть определены одновременно, иначе "остановившись" после вызова очередной функции, вы рискуете получить нежизнеспособный запрос... Зачем создавать дополнительную уязвимость, для пользователя интерфейса?
Я не хочу каждый раз помнить о том, что после условного метода...
.ДобавитьСоединение() - мне НЕОБХОДИМО вызвать еще какой-то метод... например .УсловиеОбъединения()

Методы должны делать то, что вы скорее всего "предполагаете" они делают, исходя из их наименований.

Почему вы считаете, что не следует использовать платформенную СхемаЗапроса? Она вроде предоставляет весь необходимый функционал, для построения полноценного запроса... и вероятно используется "под капотом" той же СКД.
У меня лично были претензии конкретно к ее интерфейсу... давайте я продублирую ссылку на статью на которую я ориентировался.
https://infostart.ru/1c/articles/307045/

К тому же после написания статьи, я наткнулся на похожие публикации, они более объемные и развернутые, и "текучесть" похоже не только мне показалась подходящим приемом для работы с запросами.
https://infostart.ru/1c/articles/1390402/
https://infostart.ru/1c/articles/1871072/

(8) Действительно, без ограничений не обошлось, но это вопрос расширения модуля ОбъектЗапрос там вроде не так уж трудно добавить дополнительные функции если они вам нужны.

Запрос из многих запросов - в моем примере реализовано через функции
.ДобавитьОбъединение() = это дополнительный запрос в пакете
.ДобавитьПакет() = это дополнительный пакет и запрос в нем
.Поместить() = это создание временной таблицы

Самое большое ограничение лично я вижу в использовании Вложенных запросов - я не разобрался как они реализованы в платформенном объекте СхемаЗапроса - предполагаю, что проще всего использовать какую-то версию рекурсии - создаем вложенный запрос отдельно, а затем "пропихиваем" его...

С другой стороны вложенные запросы - на мой взгляд сами по себе выглядят как своеобразный ХАК системы запросов, они сложно читаются и к счастью не так уж часто используются. Лично я чаще всего использую прием вложенного запроса к временной таблице в условии, чтобы получить список для отбора... ну знаете, вот эта штука:
ГДЕ Аналитика1, Аналитика2 В (Выбрать ВТ.ЧетТам, ВТ.ЧетЕще Из ВТ как ВТ)
21. dhurricane 08.12.23 10:14 Сейчас в теме
(13)
Зачем создавать дополнительную уязвимость, для пользователя интерфейса?
Не могу тут давать советы, вероятно Вы правы. Лишь отметил, что здесь тоже частно приходится конструировать запрос, а следовательно от текучей схемы придется вновь вернуться к конструированию строки соединения. Только не понял, почему запрос будет нежизнеспособный?

Почему вы считаете, что не следует использовать платформенную СхемаЗапроса?
Просто неудачный опыт, мне она создавала больше проблем, нежели помогала решать мои задачи. Коротко на вскидку:
- портит исходное форматирование текста;
- добавляет самостоятельно соединения, о которых "не просят";
- самостоятельно добавляет псевдонимы полей;
- "ломает" выражения расширения языка запросов для компоновки данных, добавляя свои псевдонимы и им.
14. DrZombi 301 07.12.23 12:12 Сейчас в теме
(13) Автор конечно молодец, не так много статей описывающих Схему запроса.

Я к примеру столкнулся с такой вещью, что Схема запроса автоматический подставляется "Псевдоним".

Пришлось вставить
	
        //Уберем лишние "Поле"... увы... оно тут лишнее..
	Для Каждого Выражение Из Оператор.ВыраженияОтбораКомпоновкиДанных Цикл 
		Псевдоним = Выражение.Псевдоним;
		Если Лев(Псевдоним,4) = "Поле" Тогда
			Выражение.Псевдоним = "";
		КонецЕсли;
	КонецЦикла;
	
Показать
19. user1923546 50 07.12.23 12:34 Сейчас в теме
(14) Да, поэтому функция ДобавитьПоле() получилась неожиданно сложной.
Она обязательно требует Псевдоним, чтобы было меньше путаницы, а еще пришлось учитывать вариант когда мы добавляем поле ко второму запросу в объединении

Функция ДобавитьПоле(Поле, Псевдоним) Экспорт
	Контекст = ТекучийКод.Контекст("ОбъектныеЗапросы");
	
	// ++ 001 Добавление поля - в объединение: 
	Если Контекст.Пакет.Операторы.Количество() > 1 Тогда
		// Ищем уже сущестующий индекс по псевдониму, в основной выборке.
		Индекс = 0;
		Найден = Ложь;
		Для Каждого Колонка Из Контекст.Пакет.Колонки Цикл
			Если Колонка.Псевдоним = Псевдоним Тогда
				Найден = Истина;
				Прервать;
			КонецЕсли;
			Индекс = Индекс+1;	
		КонецЦикла; 
		
		Выражение = Контекст.Выборка.ВыбираемыеПоля.Добавить(Поле); 
		// Сопоставляем 
		Контекст.Пакет.Колонки[Индекс].Поля.Установить(1, Выражение);
		
		// Если не нашли сопоставление, значит это новое поле
		Если Не Найден Тогда
			Контекст.Пакет.Колонки[Индекс].Псевдоним = Псевдоним;	
		КонецЕсли;
		
		Возврат ОбъектЗапрос;
	КонецЕсли; // -- 001
	
	ИндексНового = Контекст.Выборка.ВыбираемыеПоля.Количество();
	Выражение = Контекст.Выборка.ВыбираемыеПоля.Добавить(Поле);
	
	// Псевдонимы для колонок - указываются на уровне запроса
	Контекст.Пакет.Колонки[ИндексНового].Псевдоним = Псевдоним;  
	
	Возврат ОбъектЗапрос;
КонецФункции  
Показать
15. DrZombi 301 07.12.23 12:15 Сейчас в теме
(13) В общем я где-то на просторах инета нашел функцию, шаблон.

Функция ДобавитьВременнуюТаблицуПоСхемеЗапроса(ТекстЗапроса, ИмяВременнойТаблицы)
	Перем СхемаЗапроса;
	
	СхемаЗапроса = Новый СхемаЗапроса;
	СхемаЗапроса.УстановитьТекстЗапроса(ТекстЗапроса);
	
	//получим последний запрос пакета, к которому будем присоединять таблицу
	ПоследнийЗапросПакета = СхемаЗапроса.ПакетЗапросов[СхемаЗапроса.ПакетЗапросов.Количество()-1];
	ПоследнийЗапросПакета.ТаблицаДляПомещения = ИмяВременнойТаблицы;
	
	//Каждый оператор представляет собой запрос ВЫБРАТЬ.
	Оператор = ПоследнийЗапросПакета.Операторы[0];
	
	// получаем источники оператора ВЫБРАТЬ
	Источники = Оператор.Источники;
	ОсновнойИсточник = Источники[0];
	
	////добавим к источникам наш регистр, укажем его псевдоним
	//НовыйИсточник = Источники.Добавить("Задача.ЗадачаИсполнителя.Предметы", "СОГ_ПредметыЗадач");
	//НовыйИсточник.Соединения.Очистить();
	//
	//// получим псевдоним основном таблицы для формирования условия соединения
	//ПсевдонимОсновнойТаблицы = ОсновнойИсточник.Источник.Псевдоним;
	//
	////Сформируем строку соединения ЗадачаИсполнителя.Ссылка = ПредметыЗадач.Ссылка ЗадачаИсполнителя
	//УсловиеСоединения = ПсевдонимОсновнойТаблицы + ".Ссылка = СОГ_ПредметыЗадач.Ссылка";
	//УсловиеСоединения2 = "(СОГ_ПредметыЗадач.РольПредмета = ЗНАЧЕНИЕ(Перечисление.РолиПредметов.Основной))";
	//
	//// получим соединения основного источника и добавим к нему своё
	//Соединения = ОсновнойИсточник.Соединения;
	//Соединения.Добавить(НовыйИсточник, УсловиеСоединения);
	//Соединения.Добавить(НовыйИсточник, УсловиеСоединения2);
	//
	//// установим тип соединения
	//Соединения[Соединения.Количество()-1].ТипСоединения = ТипСоединенияСхемыЗапроса.ЛевоеВнешнее;	
	
	//// чтобы в динамическом списке стало доступно для вывода поле из нашего регистра, добавим его в запрос
	//ДобавленнеПоле = Оператор.ВыбираемыеПоля.Добавить("СправочникПодразделенияОрганизаций.Расформировано");	// КАК СОГ_ПредметыЗадач_Содержание
	//
	//ПоследняяКолонка = ПоследнийЗапросПакета.Колонки.Количество()-1;
	//Колонка = ПоследнийЗапросПакета.Колонки[ПоследняяКолонка];
	//Колонка.Псевдоним = "Расформировано";
	
	//Уберем лишние "Поле"... увы... оно тут лишнее..
	Для Каждого Выражение Из Оператор.ВыраженияОтбораКомпоновкиДанных Цикл 
		Псевдоним = Выражение.Псевдоним;
		Если Лев(Псевдоним,4) = "Поле" Тогда
			Выражение.Псевдоним = "";
		КонецЕсли;
	КонецЦикла;
	
	//{ЛЕВОЕ СОЕДИНЕНИЕ Задача.ЗадачаИсполнителя.Предметы КАК ПредметыЗадач
	//ПО ЗадачаИсполнителя.Ссылка = ПредметыЗадач.Ссылка
	//	И (ПредметыЗадач.РольПредмета = ЗНАЧЕНИЕ(Перечисление.РолиПредметов.Основной))}
	
	НовыйТекстЗапроса = СхемаЗапроса.ПолучитьТекстЗапроса();
	Возврат НовыйТекстЗапроса;
КонецФункции
Показать
17. user1923546 50 07.12.23 12:25 Сейчас в теме
(15) Оберните текст функции в блок кода. Спасибо! ٩(◕‿◕。)۶
18. DrZombi 301 07.12.23 12:30 Сейчас в теме
22. DemetrKlim 184 11.12.23 09:38 Сейчас в теме
Какая-то дивная "матрешка" получилась) Я СхемойЗапроса пользуюсь часто и с удовольствием. Но не думал, что хотелось бы что-то доработать - пока нравится штатный механизм.
23. Alxby 1116 28.12.23 18:57 Сейчас в теме
Хранить данные в контексте, созданном в модуле повторного использования? Он живет ограниченное время. И окончание этого срока жизни (а значит создание новой, чистой структуры контекста) вполне может произойти между добавлением поля и группировки.))
24. Жолтокнижниг 259 27.02.24 01:30 Сейчас в теме
(23) К сожалению может, но если вы поставили точку останова и пошли курить на 20 минут и база должна быть клиент-серверной.
25. Alxby 1116 27.02.24 09:24 Сейчас в теме
(24)К сожалению, значение в кэше модуля повторного использования может быть удалено в не только в этом случае. ИТС: "... Кроме этого значение будет удалено при нехватке оперативной памяти в рабочем процессе сервера, при перезапуске рабочего процесса и при переключении клиента на другой рабочий процесс....". Вообще говоря, использовать переопределяемый модуль для хранения значения - это не то, для чего этот механизм предназначен. Для целей статьи гораздо проще и надежнее хранить контекст в переменной и передавать его в качестве параметра во все функции.
user1923546; +1 Ответить
26. Жолтокнижниг 259 27.02.24 14:36 Сейчас в теме
(25) Согласен, но есть нюанс, оно работает.
Советую посмотреть код, сам контекст не хранится в модуле повторного использования, там хранится адрес временного хранилища.
Сам не посмотрел код, думал такой же подход как в yaxunit.
Да в такой схеме ошибки возможно, но надо тестировать (причем на разных версиях поведение может быть разным). Вероятность ошибок вырастает, если работа со схемой будет перемежаться другим кодом, например, сформировали схему, выполнили запрос/отчет, доработали схему.
user1923546; +1 Ответить
27. user1923546 50 08.10.24 16:26 Сейчас в теме
(26)
Спасибо за подсказку Вам и Alxby. Хранить контекст в переменной, тоже кажется мне хорошим решением, но не могу сразу сообразить, как это повлияет на все решение целиком.

// ОбщийМодуль.ТекучийКод Сохранение контекста во временное хранилище.

Функция ХранилищеКонтекста(Строка_УИД) Экспорт
	Возврат ПоместитьВоВременноеХранилище(Новый Структура()); 
КонецФункции


Соответственно в модуле ОбъектЗапрос нам понадобится чуть больше действий.
Во первых я думаю надо объявить понятную остнастку.
Процедура СоздатьКонтекст()
	ТекучийКод.ХранилищеКонтекста("ОбъектныеЗапросы");
КонецПроцедуры 

Процедура СохранитьКонтекст(Структура)
	ПоместитьВоВременноеХранилище(Структура, ТекучийКод.ХранилищеКонтекста("ОбъектныеЗапросы"));
КонецПроцедуры

Функция ПолучитьКонтекст()                                   
	Возврат ПолучитьИзВременногоХранилища(ТекучийКод.ХранилищеКонтекста("ОбъектныеЗапросы"));
КонецФункции
Показать


Во вторых в КАЖДОЙ функции модуля использующего "Контекст"
его потребуется не только ПОЛУЧАТЬ, но и СОХРАНЯТЬ, например:
Функция Разрешенные(Да=Истина) Экспорт
	Контекст = ПолучитьКонтекст(); //ТекучийКод.Контекст("ОбъектныеЗапросы");
	Контекст.Пакет.ВыбиратьРазрешенные = Да; 
	
	СохранитьКонтекст(Контекст);
	Возврат ОбъектЗапрос;	
КонецФункции 
Показать
28. user1923546 50 15.10.24 10:21 Сейчас в теме
(26) Пытался исправить код, так чтобы хранить адрес временного хранилища, но к сожалению стало только хуже.
Срабатывает 1 раз.
Может вы подскажете, как сделать это надежнее?

Пока что у меня получается, что хранить контекст в переменной и передавать в каждую процедуру - действительно самый лучший способ...
Оставьте свое сообщение