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

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    125007    683    389    

732

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

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

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

11.04.2024    2256    andrey_sag    10    

28

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

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

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

13.02.2024    6009    KawaNoNeko    23    

25

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

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

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

1 стартмани

31.01.2024    2150    2    Yashazz    0    

31

Запрос 1С copilot

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

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

5 стартмани

15.01.2024    6649    31    mkalimulin    27    

52

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

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

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

14.12.2023    1883    vandalsvq    7    

29

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

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

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

06.12.2023    5628    user1923546    26    

46

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    16602    skovpin_sa    14    

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

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

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

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

Эх... Рискну!
5. DitriX 2093 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 291 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 291 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 1715 12.05.16 02:41 Сейчас в теме
Для решения мелких задач - встречается:
&НаСервере
Процедура ВыполнитьКод(Код, Параметр=неопределено)
  Выполнить(Код);
КонецПроцедуры

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

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