В разработке на платформе 1С:Предприятие 8.3 (особенно в управляемых формах) одной из самых частых задач является получение данных из базы на сервере и их передача для отображения или обработки пользователю на клиент. Разберем подробно, как правильно организовать этот процесс, избегая типичных ошибок новичков.
Прежде всего, проанализируем ситуацию: почему мы не можем просто выполнить запрос на клиенте? В управляемом приложении работа с базой данных (объекты Запрос, Справочники, РегистрыСведений) разрешена только в серверном контексте. Поэтому механизм всегда состоит из двух этапов:
Возврат.Важно помнить о сериализации: с сервера на клиент можно передавать только простые типы данных (числа, строки, даты, булево) или специальные коллекции, такие как Структура или Массив. Вы не сможете передать сам объект РезультатЗапроса или ВыборкаИзРезультатаЗапроса — их нужно «распаковать» на сервере.
Рассмотрим пример, когда нам нужно получить курс валюты из регистра сведений. Разберем по шагам правильный код серверной функции и клиентской процедуры.
Серверная часть:
&НаСервере
Функция ПолучитьКурсВалюты(ВыбВалюта)
Запрос = Новый Запрос;
// Используем параметры виртуальной таблицы для оптимизации
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ВалютыСрезПоследних.Курс КАК Курс
|ИЗ
| РегистрСведений.КурсыВалют.СрезПоследних(, Валюта = &Валюта) КАК ВалютыСрезПоследних";
Запрос.УстановитьПараметр("Валюта", ВыбВалюта);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
// Возвращаем конкретное числовое значение
Возврат Выборка.Курс;
Иначе
// Если данных нет, лучше вернуть 0, чтобы избежать ошибок в расчетах на клиенте
Возврат 0;
КонецЕсли;
КонецФункции
Клиентская часть:
&НаКлиенте
Процедура ВалютаПриИзменении(Элемент)
// Вызываем серверную функцию и передаем в нее значение из реквизита формы
ТекущийКурс = ПолучитьКурсВалюты(Объект.Валюта);
// Теперь переменная ТекущийКурс содержит число, полученное из запроса
Сообщить("Актуальный курс: " + ТекущийКурс);
// Можем записать значение в другой реквизит
Объект.КурсДокумента = ТекущийКурс;
КонецПроцедуры
Проанализируем ситуацию, когда нам не нужно писать сложный запрос. Платформа предоставляет удобный метод для работы с регистрами сведений — ПолучитьПоследнее(). Это работает быстрее и код выглядит чище.
Рассмотрим реализацию:
&НаСервере
Функция ПолучитьКурсОптимизировано(ВалютаСсылка, ДатаСреза)
// Метод возвращает Структуру, содержащую значения всех ресурсов регистра
ДанныеКурса = РегистрыСведений.КурсыВалют.ПолучитьПоследнее(ДатаСреза, Новый Структура("Валюта", ВалютаСсылка));
// Возвращаем значение ресурса "Курс"
Возврат ДанныеКурса.Курс;
КонецФункции
Этот метод предпочтителен, так как система сама формирует оптимальный запрос к базе данных. Если на указанную дату записи нет, метод вернет структуру с пустыми значениями (например, 0 для чисел), что не приведет к ошибке.
Разберем основные моменты, на которых часто спотыкаются разработчики:
СрезПоследних) фильтры нужно устанавливать в параметрах таблицы, а не в секции ГДЕ. Это критически влияет на производительность.Неопределено или пустую строку, а на клиенте вы попытаетесь умножить это на число, программа выдаст ошибку. Всегда приводите результат к нужному типу (например, через 0).МояПеременная = ИмяФункции();. Если просто написать ИмяФункции();, результат будет получен сервером, но «потерян» при возврате на клиент.Часто возникает вопрос: как получить адрес, телефон или код организации? Выясним причины, почему это работает иначе.
Код ЕДРПОУ (или ОКПО) обычно является реквизитом справочника Организации или Контрагенты. Его получить проще всего:
&НаСервереБезКонтекста
Функция ПолучитьКодОрганизации(ОрганизацияСсылка)
// Обращение через точку на сервере допустимо и работает быстро
Возврат ОрганизацияСсылка.КодПоОКПО;
КонецФункции
Что касается адресов и телефонов, то в современных конфигурациях они хранятся в специальном регистре или табличной части. Для их получения лучше использовать функции БСП (Библиотеки Стандартных Подсистем):
&НаСервере
Функция ПолучитьАдресКонтрагента(Контрагент)
// Пример использования типовых механизмов
Данные = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(Контрагент, Справочники.ВидыКонтактнойИнформации.ЮрАдресКонтрагента);
Если Данные.Количество() > 0 Тогда
Возврат Данные[0].Представление;
КонецЕсли;
Возврат "";
КонецФункции
Таким образом, мы рассмотрели основные способы извлечения данных из базы и их передачи между программными слоями 1С. Главное — всегда контролировать типы передаваемых данных и использовать возможности серверного контекста максимально эффективно.