Запросы &НаКлиенте для Управляемого приложения

07.08.16

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

Разбитый между клиентом и сервером код размывает и усложняет логику прикладного решения. Для запроса из базы данных одной записи предлагаю &НаКлиенте использовать универсальную процедуру "ЗаполнитьИзЗапроса".

Скачать исходный код

Наименование Файл Версия Размер
Пример работы с процедурой "ЗаполнитьИзЗапроса"
.epf 9,06Kb
3
.epf 2 9,06Kb 3 Скачать
Тест производительности
.epf 10,25Kb
1
.epf 10,25Kb 1 Скачать

Процедура "ЗаполнитьИзЗапроса" сокращает и упрощает прикладной код:

  1. Запрос к базе данных составляется непосредственно в обработчике событий формы;
  2. Значения реквизитов формы процедура самостоятельно считывает в качестве параметров запроса;
  3. Значения реквизитов формы процедура самостоятельно заполняет результатом выборки данных.

По производительности процедура "ЗаполнитьИзЗапроса" медленнее традиционно реализованных процедур &НаСервереБезКонтекста, но быстрее, чем &НаСервере (с контекстом).

В обновленной публикации:

  • В процедуру "ЗаполнитьИзЗапроса" добавлена возможность указания имен параметров запроса в явном виде - это исключает дополнительный вызов сервера для автоматического определения перечня параметров Запроса;
  • Подправлен код;
  • Добавлена обработка для оценки производительности процедуры  "ЗаполнитьИзЗапроса".

Процедура ЗаполнитьИзЗапроса принимает четыре параметра:

  • ОбъектПриемник - куда копировать результат запроса;
  • ТекстЗапроса - стандартный параметризованный запрос;
  • ОбъектИсточник - откуда брать параметры для Запроса - необязательный параметр, по умолчанию используется ОбъектПриемник;
  • СтруктураПараметровЗапроса - необязательное перечисление параметров запроса и их значений. Исключает дополнительный вызов сервера для автоматического определения имен параметров в Запросе.

Пример заполнения на форме “КурсаВалюты” &НаКлиенте через предлагаемую процедуру:

Порядок работы процедуры ЗаполнитьИзЗапроса:

  1. Если СтруктураПараметровЗапроса не указана явно, параметры определяются в ТекстеЗапроса автоматически  &НаСервереБезКонтекста;
  2. &НаКлиенте СтруктураПараметровЗапроса заполняется значениями свойств ОбъектаИсточника (символ “_” (подчеркивание) в имени параметра запроса интерпретируется как “.” (точка) для доступа к вложенным свойствам объекта);
  3. &НаСервереБезКонтекста выполняется ТекстЗапроса;
  4. &НаКлиенте заполняются свойства ОбъектаПриемника значениями полей результирующей таблицы Запроса (символ “_” (подчеркивание) в имени поля интерпретируется как “.” (точка) для доступа к вложенным свойствам объекта).

Оценка производительности для толстого клиента:

  • Процедура ЗаполнитьИзЗапроса (п.2.2.) выполняется в 1,5 раза медленнее традиционно реализованной функции на &НаСервереБезКонтекста (п.1.3.), но в 2 раза быстрее процедуры на &НаСервере (с контекстом) (п.1.4.);
  • Автоматическое определение параметров запроса увеличивает время выполнение процедуры ЗаполнитьИзЗапроса в 1,7 раза  (п.2.3.). Данную опцию удобно использовать на этапе отладки, когда параметры запроса окончательно не определены.
  • ЛЮБОПЫТНО! Вызов клиентом сервера без контекста (п.1.3.) в 3!!! раза медленнее обращения сервера к БД (п.2.1.).

Ниже представлен код реализованных процедур:

&НаКлиентеНаСервереБезКонтекста
Процедура ЗаполнитьИзЗапроса(ОбъектПриемник, Знач ТекстЗапроса, Знач ОбъектИсточник=Неопределено, Знач СтруктураПараметровЗапроса=Неопределено)  
	ОбъектИсточник = ?(ОбъектИсточник=Неопределено,ОбъектПриемник,ОбъектИсточник);
	
	Если ТипЗнч(СтруктураПараметровЗапроса)<>Тип("Структура") тогда
		СтруктураПараметровЗапроса = Новый Структура;
		
		Для каждого ИмяПараметра Из ИменаПараметровЗапроса(ТекстЗапроса) Цикл
			СтруктураПараметровЗапроса.Вставить(ИмяПараметра);
		КонецЦикла;         
	КонецЕсли;
	 
		
	Для каждого Параметр Из СтруктураПараметровЗапроса Цикл
		Если Параметр.Значение=Неопределено тогда
			Попытка
				СтруктураПараметровЗапроса.Вставить(Параметр.Ключ, ПрочитатьВложенныйОбъект(ОбъектИсточник, Параметр.Ключ));
			Исключение
				СтруктураПараметровЗапроса.Вставить(Параметр.Ключ, Null);
					
			КонецПопытки;
		КонецЕсли;
	КонецЦикла;         
	
	МассивЗначений = ЗаполнитьМассивРезультатомЗапроса(СтруктураПараметровЗапроса, ТекстЗапроса, 1);
	
	Если МассивЗначений.Количество()>0 тогда
		Для каждого Колонка Из МассивЗначений[0] Цикл
			Попытка
				ЗаписатьВоВложенныйОбъект(Колонка.Значение,  ОбъектПриемник, Колонка.Ключ)	
			Исключение
				
			КонецПопытки;
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция ПрочитатьВложенныйОбъект(Объект, Путь="", Разделитель="_")
	ПозицияРазделителя = Найти(Путь, Разделитель);
	
	Если ПозицияРазделителя=0 тогда
		ПозицияРазделителя=СтрДлина(Путь)+1;
	КонецЕсли;	
	
	ИмяВложенногоОбъекта=Сред(Путь,1,ПозицияРазделителя-1);
	ОставшийсяПуть=Сред(Путь,ПозицияРазделителя+1);
	
	Если ИмяВложенногоОбъекта="" тогда
		Возврат Объект;
	КонецЕсли;
	
	Если ОставшийсяПуть="" тогда
		Возврат Объект[ИмяВложенногоОбъекта];
	КонецЕсли;
	
	Возврат ПрочитатьВложенныйОбъект(Объект[ИмяВложенногоОбъекта], ОставшийсяПуть, Разделитель);	
КонецФункции

&НаКлиентеНаСервереБезКонтекста
Процедура ЗаписатьВоВложенныйОбъект(Значение, Объект, Путь="", Разделитель="_")
	ПозицияРазделителя = Найти(Путь, Разделитель);
	
	Если ПозицияРазделителя=0 тогда
		ПозицияРазделителя=СтрДлина(Путь)+1;
	КонецЕсли;	
	
	ИмяВложенногоОбъекта=Сред(Путь,1,ПозицияРазделителя-1);
	ОставшийсяПуть=Сред(Путь,ПозицияРазделителя+1);
	
	Если ИмяВложенногоОбъекта="" тогда
		Объект=Значение;
		Возврат;
	КонецЕсли;
	
	Если ОставшийсяПуть="" тогда
		Объект[ИмяВложенногоОбъекта]=Значение;
		Возврат;
	КонецЕсли;
	
	ЗаписатьВоВложенныйОбъект(Значение, Объект[ИмяВложенногоОбъекта], ОставшийсяПуть, Разделитель);	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ИменаПараметровЗапроса(ТекстЗапроса)  
	Запрос = Новый Запрос(ТекстЗапроса);
	
	МассивПараметров = Новый Массив;
	
	Для каждого Параметр Из Запрос.НайтиПараметры() Цикл
		  МассивПараметров.Добавить(Параметр.Имя)
	КонецЦикла;
	
	Возврат МассивПараметров;
КонецФункции

&НаСервереБезКонтекста
Функция ЗаполнитьМассивРезультатомЗапроса(СтруктураПараметров, ТекстЗапроса, КоличествоЗаписей=0) 
	Запрос = Новый Запрос(ТекстЗапроса);
	
	Для каждого Параметр Из СтруктураПараметров Цикл
		  Запрос.УстановитьПараметр(Параметр.Ключ, Параметр.Значение);
	КонецЦикла;
	
	РезультатЗапроса = Запрос.Выполнить();
	
	МассивИменКолонок = Новый Массив;
	Для каждого Колонка Из РезультатЗапроса.Колонки Цикл
		МассивИменКолонок.Добавить(Колонка.Имя);
	КонецЦикла;
	
	ВыборкаЗаписей = РезультатЗапроса.Выбрать();
	РезультирующийМассив = Новый Массив();
	
	Если ВыборкаЗаписей.Следующий() тогда
		СтруктураДанных = Новый Структура();
		
		Для каждого ИмяКолонки Из МассивИменКолонок Цикл
			СтруктураДанных.Вставить(ИмяКолонки, ВыборкаЗаписей[ИмяКолонки]);
		КонецЦикла;
		
		РезультирующийМассив.Добавить(СтруктураДанных);
		
		Если КоличествоЗаписей<>1 тогда
			ВыбраноЗаписей=1;
			
			Пока ВыборкаЗаписей.Следующий() и (ВыбраноЗаписей<КоличествоЗаписей или КоличествоЗаписей=0) цикл
				СтруктураДанных = Новый Структура();
				
				Для каждого ИмяКолонки Из МассивИменКолонок цикл
					СтруктураДанных.Вставить(ИмяКолонки, ВыборкаЗаписей[ИмяКолонки]);
				КонецЦикла;
				
				РезультирующийМассив.Добавить(СтруктураДанных);
				
				ВыбраноЗаписей=ВыбраноЗаписей+1;
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;

	Возврат РезультирующийМассив;
КонецФункции


Запрос База данных Клиент Управляемое приложение

См. также

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

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

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

10000 руб.

02.09.2020    129742    700    390    

752

Как посмотреть итоговый запрос в отчете СКД

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

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

15.05.2024    2953    implecs_team    4    

34

Пропорциональное распределение в запросе с использованием АвтоНомерЗаписи()

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

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

11.04.2024    2619    andrey_sag    10    

32

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    6300    KawaNoNeko    23    

26

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2291    2    Yashazz    0    

32

Запрос 1С copilot

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

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

15.01.2024    7115    40    mkalimulin    32    

53

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

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

14.12.2023    2015    vandalsvq    7    

29

Консоль запросов УФ 8.3.2.24.12 (мод от Dr.Zombi)

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Запросы Россия Абонемент ($m)

Работа с запросом и СКД, Полная поддержка пакетных запросов, временных таблиц. Главное скорость отладки запроса и данных, а красота вторична.

1 стартмани

07.12.2023    3483    52    DrZombi    54    

21
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. GROOVY 2507 08.05.16 17:39 Сейчас в теме
Шикарно. Сериализовать весь результат любого запроса и передавать его на клиента. Прям слов нет.
theshadowco; DrAku1a; kuzyara; 1С_Мастер; PrinzOfMunchen; cleaner_it; +6 Ответить
3. sereginseregin 22 09.05.16 18:30 Сейчас в теме
(1) GROOVY,
Сериализовать весь результат любого запроса и передавать его на клиента

  • Данных передается не больше, чем необходимо &НаКлиенте в каждом конкретном случае. (...немного схалтурил-недоделал с "КоличествоСтрок=0", но) Какой ...разработчик определяет в запросах выборку лишних полей или строк.
  • Когда разработчиков >3, форм >100, а заказчик требует "реактивного" решения, на первый план выходит простота и наглядность прикладного кода.
  • Подобное применение запросов &НаКлиенте переводит код из императивного ближе в декларативный.

Шикарно... Прям слов нет.
- конструктивно!


2. DitriX 2096 09.05.16 18:22 Сейчас в теме
Это может потребоваться только в той конфигурации - где результат запроса ВСЕГДА будет разный, в противном случае - достаточно использовать общие модули с галокой - повторного использования, иначе, при более менее средних объмах - рискуете убить нафиг все :)
Ну и второе - это что, всегда при получении курса писать запрос? :)
Вобщем я бы на вашем месте скрыл эту статью :)
CanibalHOM; theshadowco; DrAku1a; GROOVY; awk; +5 Ответить
4. sereginseregin 22 09.05.16 19:22 Сейчас в теме
(2) DitriX,
Это может потребоваться только в той конфигурации - где результат запроса ВСЕГДА будет разный,

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

надеялся понятно, процедуры надо раскидать по общим модулям, или Вы о другом?
Ну и второе - это что, всегда при получении курса писать запрос? :)

Я за здоровый компромисс, в простейших формах используйте общую функцию КурсВалюты,
Бывают ситуации, значения валюты или даты не находятся на форме, а вычисляются по ссылке с замороченными условиями, поэтому вычисление этих условий напрямую в запросе курса валюты может выглядеть нагляднее, но это ... Вам решать.
Вобщем я бы на вашем месте скрыл эту статью :)

Эх... Рискну!
5. DitriX 2096 09.05.16 19:44 Сейчас в теме
Я к тому, что не зря их разносят по модулям, почитайте про то, что такое модуль повторного использования.
И тогда сразу станет понятно - почему описаный вами механиз не просто узкоспециализированный, а по сути и бесполезный.
Т.е. вы сами нарисовали сферического коня в вакууме, и говорите о том, что он реальный. Не, ну никто же не спорит, почему же этому механизму то не работать?
Но вот если я при найме на работу, или при приеме самой работы - увидел бы такое решение, я бы послал передлывать, и не за-за того, что я такой злой и не понимаю, а наоборот.

То что вы описали - к этому народ тянулся еще лет 6 назад, и каждый второй придумывал такие костыли (и я там же был, чего уж там), но, их оставили в прошлом, и не зря.

Почему прошу скрыть - не учите плохому, не надо такое видеть неокрепшим умам, а то вы только хуже сделаете людям.
Вместо этого - описали бы минусы такого подхода, и рассказали - почему так делать нельзя, и это бы было бы и для вас интересней, и для новичков, тоже было бы весьма интересно. Та чего уж скрывать - и мне тоже :)
6. sereginseregin 22 09.05.16 22:35 Сейчас в теме
(5) DitriX,
...модуль повторного использования

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

То что вы описали - к этому народ тянулся еще лет 6 назад

К сожалению, кроме жалоб бывалых и бравады авангардистов ничего конструктивного не нашел

не учите плохому, не надо такое видеть неокрепшим умам
Ваше мнение поможет этим умам критичнее подойти к предлагаемому решению

Вместо этого - описали бы минусы такого подхода
Много лет, НО не в 1С, успешно использую данный подход с классическим SQL. Вычисления выполняются на СУБД - проблем со нагрузкой никаких. Клиент только для отображения данных.

Решил таки (перед пенсией:-) освоить плюшки и кружева 1С. Лучший способ обучения - показать свое решение, получить отзыв. Понимаю, полез в чужой монастырь со своим уставом, но в чем религии у нас разные, все равно, пока не понял.
7. petrov_al 10 10.05.16 12:03 Сейчас в теме
По моему решение очень оригинальное и применимо. А то что автор не знает в чем особенность модуля повторного использования ...это упустим.
8. dabu-dabu 293 10.05.16 12:17 Сейчас в теме
Оригинального особо ничего нет. Очередная попытка сделать универсальную функцию которая облегчит жизнь. Как показывает практика долго такие штуки не живут, т.к. в конечном итоге обрастают кучей функционала и превращаются в не поддерживаемых медленных монстров.

Ошибки в коде:
1. У функции "ЗаполнитьИзЗапроса" 2 вызова сервера: ИменаПараметровЗапроса, ЗаполнитьМассивРезультатомЗапроса. Причем от задвоенности совершенно легко избавиться. За такие штуки минимум - лишать премии.
2. У функции ЗаполнитьМассивРезультатомЗапроса есть безобразная строчка "СтруктураДанных = Новый Структура(МассивИменКолонок)".

Допущенные ошибки говорят о том что вы как программист достаточно слабый и малоопытный.
Соответственно, лучше бросайте заниматься фигней такой как "разработка универсальных функций облегчающих жизнь". То что они облегчают жизнь - это только кажется на первый взгляд.
Fox-trot; +1 Ответить
9. sereginseregin 22 10.05.16 13:43 Сейчас в теме
(8) dabu-dabu,
Как показывает практика ... превращаются в не поддерживаемых медленных монстров

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

Вам непривычно писать запросы? А у меня после тысячи написанных SQL рука не поднимается обрабатывать данные циклами - слишком много вспомогательных переменных, и индексы не работают. Я вообще перестал понимать, для чего использовать циклы в базах данных, когда все операции работают через SQL, но это пока не про 1C.

В 1С выглядит как костыль? Согласен, помогите, как это в 1С будет работать правильней.

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


У функции "ЗаполнитьИзЗапроса" 2 вызова сервера: ИменаПараметровЗапроса, ЗаполнитьМассивРезультатомЗапроса. Причем от задвоенности совершенно легко избавиться.

Если обе функции находятся в общем модуле, ничего не знают о контексте формы, как Вы собираетесь их объединить без 2-го пункта:
1. На сервере стандартной функцией определяются имена параметров Запроса;
2. На клиенте заполняются параметры Запроса значениями реквизитов формы;
3. На сервере выполняется Запрос.

У функции ЗаполнитьМассивРезультатомЗапроса есть безобразная строчка "СтруктураДанных = Новый Структура(МассивИменКолонок)"

Согласен, МассивИменКолонок тут лишний. Видимо осталось, когда искал варианты, как быстрее выборку засунуть в массив.

Постараюсь подправить эту опечатку, и еще кое что в ближайшее время...


То что они облегчают жизнь - это только кажется на первый взгляд.


Программист пишет - зарплата капает!
10. dabu-dabu 293 10.05.16 16:14 Сейчас в теме
(9)
1. При чем здесь
выжимка из долгоиграющего монстра (не 1С)
когда пример именно про платформу 1С и при чем здесь
Вам непривычно писать запросы?
Осталю без комментариев.


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


2.
как Вы собираетесь их объединить без 2-го пункта
Могу посоветовать только учится программировать.

3.
Программист пишет - зарплата капает!
Т.е. ценность вашей деятельности в потраченном времени? Не завидую.
11. sereginseregin 22 10.05.16 17:28 Сейчас в теме
(9) dabu-dabu,
[IS-QUOTE]Программист пишет - зарплата капает!

Т.е. ценность вашей деятельности в потраченном времени? Не завидую.[/IS-QUOTE]
Э-эх! Знак вопроса после "капает" не поставил - теперь сам виноват.

как раз и показывает то о чем я говорю:
долго такие штуки не живут

Занимаюсь я подобными проектами в свободное от работы время. Какие-то идеи удается внедрить в рабочих проектах. Какие-то естественно отмирают. Условно удачных 60 к 40 неудачным, и это нормально. Если у Вас наоборот, не экспериментируйте.


Могу посоветовать только учится программировать.

Диалог пришел в тупик.
12. igormiro 714 10.05.16 17:39 Сейчас в теме
Ничего не обычного в статье я не нашел, а статью надо переименовать, передача параметров запроса с сервера на клиент.
13. DrAku1a 1723 12.05.16 02:41 Сейчас в теме
Для решения мелких задач - встречается:
&НаСервере
Процедура ВыполнитьКод(Код, Параметр=неопределено)
  Выполнить(Код);
КонецПроцедуры

&НаСервере
Функция ВычислитьКод(Код, Параметр=неопределено)
  Возврат Вычислить(Код);
КонецФункции

&НаСервере
Функция ВыполнитьЗапрос(ТекстЗапроса, Параметры=неопределено, КодОбработкиРезультата=неопределено)
  Запрос = новый Запрос(ТекстЗапроса);
  Если ТипЗнч(Параметры)=Тип("Структура") Тогда
    Для каждого П из Параметры Цикл Запрос.УстановитьПараметр(П.Ключ, П.Значение); КонецЦикла;
  КонецЕсли; 
  Результат = Запрос.Выполнить();
  Если КодОбработкиРезультата=неопределено Тогда
    Результат = Результат.Выгрузить().ВыгрузитьКолонку( 0 );
  Иначе
    Вычислить(КодОбработкиРезультата);
  КонецЕсли;
  Возврат Результат;
КонецФункции
Показать
Оставьте свое сообщение