Механизм «История данных», встроенный в платформу 1С:Предприятие, предоставляет разработчикам удобный и быстрый способ логирования изменений объектов базы данных. В отличие от версионирования программными средствами (например, через Библиотеку стандартных подсистем), платформенная история данных работает на уровне СУБД, что обеспечивает высокую производительность. Однако при попытке программно проанализировать настройки метаданных и узнать, включено ли версионирование для конкретного объекта, разработчики часто сталкиваются с неочевидным поведением платформы.
В этой статье мы подробно разберем, почему возникает популярная ошибка «Переменная не определена: ИспользованиеИсторииДанных», как правильно получить булево значение настройки программным путем, а также рассмотрим особенности функционирования этого механизма в современных версиях платформы 1С:Предприятие 8.3.
---
Попытки разработчиков обратиться к свойству напрямую часто выглядят следующим образом:
// Ошибочный вариант, который приведет к ошибке компиляции
Если Метаданные.Справочники.Товары.ИсторияДанных = ИспользованиеИсторииДанных.Использовать Тогда
// Какая-то логика
КонецЕсли;
При выполнении этого кода на сервере система выдаст ошибку: «Переменная не определена (ИспользованиеИсторииДанных)». Почему так происходит, ведь тип свойства ИсторияДанных в синтакс-помощнике четко определен как ИспользованиеИсторииДанных?
Дело в том, что ИспользованиеИсторииДанных не является глобальным системным перечислением общего назначения (таким как, например, ОбходРезультатаЗапроса или РежимПроведенияДокумента). Платформа 1С позиционирует его как перечисление свойств объектов метаданных. Доступ к нему из программного кода ограничен, и напрямую в области видимости сервера оно отсутствует.
Дополнительные сложности могут возникать в средах разработки, отличных от стандартного конфигуратора. Например, в ранних версиях 1С:EDT (Enterprise Development Tools) валидатор кода долгое время подсвечивал аналогичные конструкции как ошибочные, выдавая предупреждение: «Свойство ПеречислимыеСвойстваОбъектовМетаданных.ИспользованиеИсторииДанных не определено». В современных версиях EDT и платформы это поведение стандартизировано, но доступ к типу по-прежнему требует особого обращения.
---
Для того чтобы обойти это ограничение и получить корректное сравнение в коде, нам нужно обратиться к системному перечислению через коллекцию метаданных свойств объектов. Полный правильный путь выглядит так:
Метаданные.СвойстваОбъектов.ИспользованиеИсторииДанных.Использовать
Рассмотрим подробный пример функции, которая принимает имя справочника и возвращает привычное нам значение типа Булево (включена история или нет):
&НаСервере
Функция ИсторияДанныхВключена(ИмяСправочника) Экспорт
// Получаем объект метаданных для справочника
ОбъектМетаданных = Метаданные.Справочники[ИмяСправочника];
// Проверяем, существует ли справочник
Если ОбъектМетаданных = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
// Получаем значение свойства ИсторияДанных
ТекущееНастройка = ОбъектМетаданных.ИсторияДанных;
// Выполняем сравнение через системную коллекцию свойств
Если ТекущееНастройка = Метаданные.СвойстваОбъектов.ИспользованиеИсторииДанных.Использовать Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Этот код абсолютно работоспособен на любых версиях платформы 1С, начиная с 8.3.11, включая самые актуальные релизы (8.3.24 и новее). Он не зависит от режима совместимости конфигурации.
---
Если во времена платформы 8.3.13 возможности управления историей данных были жестко ограничены рамками Конфигуратора, то современные релизы платформы принесли кардинальные улучшения, о которых необходимо знать каждому разработчику:
ПриЗаписи() программно изменялись реквизиты объекта (например, заполнялся служебный комментарий или статус), эти изменения попадали в записываемую версию истории данных, но фактически не фиксировались в самой физической таблице базы данных. Это приводило к рассинхронизации версий. В последних версиях платформы этот баг был окончательно закрыт.ОбновлятьИсториюДанныхСразуПослеЗаписи. Это позволяет избежать задержек, когда изменения в истории появляются только после отработки регламентного задания.ВыполнятьОбработкуПослеЗаписиВерсииИсторииДанных.---
Для эффективной работы с историей изменений важно понимать, как платформа взаимодействует с базой данных "под капотом":
_DataHistoryQueue0. Данная операция транзакционна, но быстра и не создает блокировок. Только после вызова метода ИсторияДанных.ОбновитьИсторию() (который обычно крутится на регламентном задании) происходит разбор очереди и перенос дельт в постоянное хранилище _DataHistoryVersions. Если вы программно записали объект и тут же пытаетесь прочесть его историю — вы ничего не увидите, пока не отработает обновление очереди.ИсторияДанных.УдалитьВерсии() требует осторожности. Если вы удалите старые промежуточные версии, то попытка программно восстановить или сравнить более поздние версии может завершиться ошибкой «Данные истории не найдены», так как платформа потеряет опорную точку для расчета дельта-изменений.