Почему метод НайтиПоНаименованию возвращает разные результаты для разных пользователей и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Почему НайтиПоНаименованию() дает непредсказуемый результат

Метод НайтиПоНаименованию(), особенно с параметром Ложь (неточное соответствие), не гарантирует возвращение конкретного элемента, если в базе данных существует несколько записей, удовлетворяющих критерию поиска. Вот основные причины нестабильности:

  1. Отсутствие сортировки: Когда платформа выполняет поиск, она формирует запрос к СУБД. Поскольку в самом методе нельзя задать явную сортировку, СУБД возвращает записи в порядке, который она считает оптимальным. Этот порядок зависит от состояния индексов, фрагментации таблиц и плана выполнения запроса, который может меняться.
  2. Влияние RLS (ограничение доступа): Если в системе настроены правила разграничения доступа на уровне записей, запрос дополняется условиями RLS. Даже если пользователям доступны одинаковые объекты, наличие фильтров меняет план выполнения SQL-запроса, что влияет на выбор «первого» попавшегося элемента.
  3. Кэширование СУБД: Сервер базы данных активно использует кэш. Часто используемые пользователем данные могут находиться в оперативной памяти сервера, что делает их приоритетными при выборке, в то время как другой пользователь может получать данные, которые в данный момент «ближе» в кэше его сессии.

Как гарантированно найти нужный объект

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

Способ 1: Использование запросов к базе данных

Самый правильный и профессиональный путь — использование объекта Запрос. Только так вы можете гарантировать получение нужного элемента, применив явную сортировку и фильтрацию. Рассмотрим пример из практики разработки типовых решений (БСП):


Функция НайтиОбъектЗапросом(НаименованиеОбъекта)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    Справочник.Ссылка КАК Ссылка
        |ИЗ
        |    Справочник.ВнешниеОбработки КАК Справочник
        |ГДЕ
        |    Справочник.Наименование ПОДОБНО &Наименование
        |УПОРЯДОЧИТЬ ПО
        |    Справочник.ДатаСоздания УБЫВ";
    
    Запрос.УстановитьПараметр("Наименование", НаименованиеОбъекта + "%");
    
    Результат = Запрос.Выполнить();
    Если Не Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Выборка.Следующий();
        Возврат Выборка.Ссылка;
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Используя конструкцию УПОРЯДОЧИТЬ ПО, вы берете управление результатом в свои руки. Теперь платформа всегда вернет ожидаемый объект, основываясь на заданных вами критериях (например, по дате создания или коду), а не на «температуре океана» или случайном состоянии индекса СУБД.

Способ 2: Точное совпадение наименования

Если логика вашей программы подразумевает, что наименование должно быть строго определенным, всегда используйте параметр Истина в методе НайтиПоНаименованию(). Это заставит платформу искать полное совпадение строки.

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

Способ 3: Использование кода или уникальных идентификаторов

Наилучшая практика — это поиск по объектам, которые гарантированно уникальны. Если есть возможность, используйте метод НайтиПоКоду() или НайтиПоСсылке(). Если ваши внешние обработки имеют фиксированный код, обращение по нему будет работать быстрее и стабильнее любого поиска по наименованию.

Итоговые рекомендации

Проанализировав ситуацию, можно сделать следующие выводы для вашей ежедневной работы:

Применяя эти подходы, вы сделаете свой код устойчивым к изменениям в инфраструктуре сервера и обеспечите стабильную работу системы для всех пользователей.

← На главную