Перевод крупных корпоративных баз, таких как 1С:Комплексная автоматизация (редакция 2.4), с файлового режима работы на клиент-серверный вариант (x64) под управлением СУБД Microsoft SQL Server — это стандартный шаг при масштабировании бизнеса. Однако этот процесс часто выявляет скрытые проблемы в нетиповом (дописанном) функционале конфигурации. Код, который годами безупречно работал в файловой копии, в клиент-серверной архитектуре неожиданно начинает выдавать ошибки типов или вовсе отказывается открывать управляемые формы.
В этой статье мы подробно разберем, почему возникают сбои при сравнении чисел и открытии форм новых документов после переезда на x64-платформу, проанализируем технические причины этих явлений и найдем надежные способы их устранения.
---
Ситуация, когда сравнение двух числовых переменных выдает ошибку несоответствия типов на сервере, но отлично работает на клиенте или в файловой базе, встречается довольно часто. Проанализируем основные причины этого поведения.
1. Различие региональных настроек (локали) сервера и клиента
В файловой версии весь код (и клиентский, и серверный) выполняется в рамках одного процесса на локальном компьютере пользователя под управлением его операционной системы. При переходе в клиент-серверный режим код распределяется между клиентским приложением и сервером 1С:Предприятия.
Если на сервере приложений 1С или сервере СУБД установлена операционная система с англоязычной локалью (США), то системным разделителем дробной части по умолчанию является точка, а разделителем групп — запятая. На компьютерах пользователей чаще всего установлена русская локализация (разделитель дробной части — запятая, групп — пробел).
Если в коде нетипового механизма происходит неявное преобразование строки в число, например:
// Пример неявного преобразования строки в число
Число1 = Число(СтрокаДанных);
то на сервере с английской локалью попытка преобразовать строку вида "123,45" завершится ошибкой или вернет пустую конструкцию. Если разработчик подстраховал этот участок блоком Попытка ... Исключение, то переменная просто не будет инициализирована числом (останется в состоянии Неопределено или примет значение Null). При последующем сравнении:
Если Число1 > Число2 Тогда
// Действие...
КонецЕсли;
платформа выбросит системное исключение: "Операция сравнения на больше-меньше допустима только для значений совпадающих типов". Для решения этой проблемы мы рекомендуем явно обрабатывать строки перед преобразованием, очищая их от лишних разделителей:
// Безопасное приведение строки к числу
ОчищеннаяСтрока = СтрЗаменить(СтрокаДанных, ЧисленныеСимволы, "");
// Принудительно приводим разделители к единому стандарту
ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, ",", ".");
Попытка
Число1 = Число(ОчищеннаяСтрока);
Исключение
Число1 = 0;
КонецПопытки;
2. Проблемы совместимости с COM-объектами на х64 платформах
Если сравниваемые числа считываются из внешних источников (например, файлов XLS/XLSX, XML, JSON) через COM-соединения, то при переходе сервера на архитектуру x64 старые 32-разрядные драйверы (например, Microsoft Jet OLEDB) просто перестают работать в серверном контексте. В результате функции чтения возвращают пустые значения, что приводит к краху операций сравнения типов.
3. Известный баг платформы 1С версии 8.3.15.1656
Данный релиз платформы имеет зафиксированную ошибку оптимизатора работы с СУБД в режиме x64. При выполнении левых соединений в запросах СУБД MSSQL может возвращать значение NULL вместо ожидаемого числового значения по умолчанию (например, нуля). При попытке сравнить результат выборки в коде встроенного языка происходит сбой по типу данных.
---
Вторая проблема — документ создается на основании другого объекта на сервере, записывается, но его управляемая форма на клиенте не открывается. В файловой базе этот механизм отрабатывал корректно.
Выясним причину этой неполадки. В файловой базе границы контекстов "Клиент" и "Сервер" физически размыты. Передача сложных типов данных происходит без жестких ограничений. В клиент-серверной архитектуре передача любых данных между сервером приложений и тонким клиентом жестко регламентирована процессом сериализации (перевода объектов в XML/XDTO-пакеты).
Объект типа ДокументОбъект.ИмяДокумента существует только на сервере. Его невозможно передать на клиент напрямую. Попытка передать объект или форму, содержащую этот объект в качестве несериализуемого параметра, вызывает аварийное завершение работы интерфейса.
Рассмотрим, как выглядит ошибочный код, который часто пишут разработчики:
// ОШИБОЧНЫЙ ВАРИАНТ (работает в файловой, но падает на сервере х64)
&НаКлиенте
Процедура СоздатьНаОсновании(ПараметрОснование)
НовыйДокументОбъект = СоздатьДокументНаСервере(ПараметрОснование);
// Попытка открыть форму по объекту вызывает ошибку сериализации
ПараметрыФормы = Новый Структура("ЗначениеЗаполнения", НовыйДокументОбъект);
ОткрытьФорму("Документ.НетиповойДокумент.Форма.ФормаДокумента", ПараметрыФормы);
КонецПроцедуры
&НаСервере
Функция СоздатьДокументНаСервере(ПараметрОснование)
НовыйДокумент = Документы.НетиповойДокумент.СоздатьДокумент();
НовыйДокумент.Заполнить(ПараметрОснование);
Возврат НовыйДокумент; // Передача объекта на клиент!
КонецФункции
Разберем правильный, клиент-серверный подход решения этой задачи по шагам:
ДокументСсылка.ИмяДокумента. Данный тип отлично сериализуется.Ключ.Посмотрим на пример правильной реализации:
// ПРАВИЛЬНЫЙ ВАРИАНТ (универсальный для любой архитектуры)
&НаКлиенте
Процедура СоздатьНаОсновании(ПараметрОснование)
// Получаем с сервера только ссылку
СсылкаНаНовыйДокумент = СоздатьИЗаписатьДокументНаСервере(ПараметрОснование);
Если ЗначениеЗаполнено(СсылкаНаНовыйДокумент) Тогда
// Передаем ссылку в структуру параметров под ключом "Ключ"
ПараметрыФормы = Новый Структура("Ключ", СсылкаНаНовыйДокумент);
ОткрытьФорму("Документ.НетиповойДокумент.Форма.ФормаДокумента", ПараметрыФормы);
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция СоздатьИЗаписатьДокументНаСервере(ПараметрОснование)
НовыйДокумент = Документы.НетиповойДокумент.СоздатьДокумент();
НовыйДокумент.Заполнить(ПараметрОснование);
Попытка
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
Возврат НовыйДокумент.Ссылка; // Возвращаем только ссылку!
Исключение
ЗаписьЖурналаРегистрации("Создание на основании", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Неопределено;
КонецПопытки;
КонецФункции
---
Релиз платформы 8.3.15.1656, на котором работает база автора вопроса, в профессиональном сообществе признан крайне нестабильным, особенно при работе в 64-битной серверной среде под Windows Server с СУБД Microsoft SQL Server. В нем зафиксированы утечки оперативной памяти процессов rphost, ошибки кэширования метаданных и некорректная оптимизация запросов.
Для устранения системных сбоев выполним следующие действия:
1C:Enterprise 8.3 Server Agent и физически удалить содержимое каталога кэша (папки внутри директории srvinfo на сервере приложений).Выполнение этих архитектурных правил написания кода и своевременное обновление системного окружения платформы гарантируют быструю и отказоустойчивую работу вашей системы "1С:Комплексная автоматизация" в производительном режиме х64.