Исходный код C# на GitHub: dajet-metadata
Код используется проектом DaJet Studio
Проверялось на версиях платформы 1С:Предприятие от 8.3.10 до 8.3.20.
Файл DBNames располагается в таблице Params. Его содержание можно получить следующим запросом SQL:
SELECT [BinaryData] FROM [Params] WHERE [FileName] = N'DBNames';
Файл сжат по алгоритму deflate. Начинается с указания количества содержащихся в нём элементов. Содержит список структур DBNameEntry, которые описывают объекты хранения данных в СУБД: основные и вспомогательные таблицы, таблицы настроек, поля этих таблиц и т.п.
Список полей структуры DBNameEntry:
№ п/п |
Тип данных |
Описание |
1 |
UUID |
Указатель на файл объекта метаданных в таблице Config основной конфигурации прикладного решения 1С или указатель на сам объект метаданных, если объект метаданных не имеет собственного файла |
2 |
Строка |
Тип объекта метаданных, см. приложение № 1 |
3 |
Число |
Идентификатор объекта метаданных |
Нулевой UUID является системным объектом метаданных, а не нулевой - объектом метаданных, созданным пользователем. Системные объекты метаданных описывают структуры хранения таких данных как, например, настройки регистров накопления и т.п. Пользовательские объекты метаданных описывают структуры хранения пользовательских данных прикладного решения.
Значения UUID в списке объектов метаданных могут повторяться. В таких случаях такие объекты метаданных являются связанными между собой отношениями главный-подчинённый.
Примерами таких объектов могут быть:
- таблица регистра накопления и его таблица итогов;
- таблица справочника и его таблица изменений;
- табличная часть и её поле "НомерСтроки" (LineNo);
- и т.д. и т.п.
Типы объектов метаданных могут быть следующими:
- Reference (справочник);
- Document (документ);
- Fld (реквизит объекта);
- Node (план обмена);
- ReferenceChngR (таблица изменений справочника);
- и т.д. и т.п.
Идентификатор объекта метаданных это целочисленное, которое генерируется платформой 1С по порядку по мере формирования файла DBNames. Этот идентификатор уникален в пределах этого списка, а, следовательно, и в пределах каждой отдельно взятой конфигурации 1С. В случае выгрузки и загрузки конфигурации при помощи файла dt значения этих идентификаторов могут быть пересчитаны и изменены.
В редких случаях файл DBNames может содержать уже не существующие объекты конфигурации. В таких случаях файл объекта метаданных в таблице Config отсутствует.
Наименование соответствующего объекта СУБД обычно формируется из конкатенации значения второго и третьего полей структуры DBNameEntry с добавлением, в случае SQL Server, знака нижнего подчёркивания перед названием. Например, так: "_Reference22".
Фрагмент файла DBNames (начало и конец):
{106,
{100,
{00000000-0000-0000-0000-000000000000,"ODataSettings",1},
{00000000-0000-0000-0000-000000000000,"SystemSettings",2},
{00000000-0000-0000-0000-000000000000,"CommonSettings",3},
{00000000-0000-0000-0000-000000000000,"RepSettings",4},
{00000000-0000-0000-0000-000000000000,"RepVarSettings",5},
{00000000-0000-0000-0000-000000000000,"FrmDtSettings",6},
{00000000-0000-0000-0000-000000000000,"DynListSettings",7},
{00000000-0000-0000-0000-000000000000,"ExtensionsInfo",8},
{00000000-0000-0000-0000-000000000000,"UsersWorkHistory",9},
{b6addf15-6508-4218-935b-cf2e8f7966c8,"Document",10},
{00000000-0000-0000-0000-000000000000,"ExtDataSrcPrms",11},
{00000000-0000-0000-0000-000000000000,"CKindsOpt",12},
{00000000-0000-0000-0000-000000000000,"RefOpt",13},
{00000000-0000-0000-0000-000000000000,"Consts",14},
{00000000-0000-0000-0000-000000000000,"ChrcOpt",15},
{00000000-0000-0000-0000-000000000000,"AccOpt",16},
{2f175974-e5f4-4d16-9c48-59e49d6b25af,"InfoRg",17},
{28439047-46ca-4fba-9e2b-a3ac9f95a2c3,"Fld",18},
{4e75ac96-7c81-4c57-af12-a52eebdb576a,"Fld",19},
{60b7ad1c-bb42-4095-90e9-9b24ee68f2fc,"Fld",20},
{58dce880-f8da-40d8-88db-351fcd3a5151,"Reference",22},
{491db2dd-45e3-47fe-8712-4fb321db25b9,"InfoRg",24},
{1c36dbbe-38b1-4c66-81cf-e1a0b32b8779,"Fld",25},
{1b2317b0-bd6f-4381-b308-3b315e284a39,"Fld",26},
{e8d51aac-07d2-46e1-8655-0e120a0dfe0f,"Node",27},
{58dce880-f8da-40d8-88db-351fcd3a5151,"ReferenceChngR",28},
...
...
...
{d75053c5-0407-4071-ba45-bf7f293e18cd,"Const",103},
{d75053c5-0407-4071-ba45-bf7f293e18cd,"Fld",104},
{3297831b-9cb6-4bda-8e0a-f4d2d015c098,"InfoRgChngR",105}
}
}
Файл объекта метаданных располагается в таблице Config. Его содержание можно получить следующим запросом SQL:
SELECT [BinaryData] FROM [Config] WHERE [FileName] = @FileName ORDER BY [PartNo] ASC;
Как видно из запроса, файл объекта метаданных теоретически может состоять из нескольких частей, но на практике я такого не встречал. Файл сжат по алгоритму deflate. Файл содержит описание объекта метаданных. Описание его наименования, реквизитов, табличных частей и многого другого.
Идентификатор объекта метаданных используется для того, чтобы ссылаться на него, например, при определении типов данных реквизитов других объектов метаданных. Кроме этого он используется при сравнении и объединении конфигураций и везде, где нужно сослаться именно на объект метаданных.
Значение идентификатора расположено во второй строке файла вторым по счёту слева, если в качестве разделителя значений считать запятую и если это тип объекта "Перечисление". Для справочников, документов и большинства других объектов это четвёртое по счёту слева значение. В ниже приведённом фрагменте файла идентификатор перечисления выделен жирным шрифтом и подчёркнут.
5-ая строка файла, позиция 3. Для планов обмена: 4-ая строка файла, позиция 3.
Данное значение можно найти в файле DBNames таблицы Params. Подробнее смотри описание файла DBNames.
5-ая строка файла, позиция 4. Для планов обмена: 4-ая строка файла, позиция 4.
6-ая строка файла, позиция 3. Для планов обмена: 5-ая строка файла, позиция 3.
8-ая строка файла и ниже.
Первая строка этого блока (8-ая в файле) содержит количество владельцев для данного справочника. Например в примере ниже это количество равно трём (позиция 2).
Далее следуют указатели на файлы объектов метаданных, которые являются владельцами для данного справочника, таблицы Config.
Каждая ссылка на файл объекта метаданных имеет следующий вид (значение указателя выделено жирным шрифтом и подчёркнуто):
Эти же значения можно найти в файле DBNames таблицы Params. Подробнее смотри описание файла DBNames.
Начало блока описания табличных частей объекта метаданных выглядит следующим образом:
...
{932159f9-95b2-4e76-a8dd-8849fe5c5ded,2,
...
Данный блок содержит идентификатор типа коллекции табличных частей (см. приложение № 1) и количество табличных частей объекта метаданных. Обратите внимание, что для каждого типа объектов метаданных свой идентификатор коллекции табличных частей.
Ниже этого блока содержится описание табличных частей. Начало блока описания конкретной табличной части выглядит следующим образом:
...
{0,0,3df19dbf-efe7-4e31-99ad-fafb59ec1329},"Размещение",
{1,"ru","Размещение"},"",0,0}
...
Этот блок содержит уникальный идентификатор объекта метаданных типа "ТабличнаяЧасть", его имя и синоним.
Блок описания реквизитов табличной части объекта метаданных следует после блока описания конкретной табличной части. Выглядит он следующим образом:
...
{888744e1-b616-11d4-9436-004095e12fc7,7,
...
Данный блок содержит идентификатор коллекции реквизитов табличной части (см. приложение № 1) и количество реквизитов, которые содержит данная табличная часть. Ниже этого блока расположено описание каждого реквизита по отдельности:
...
{0,0,baf12d47-fbfe-4563-aa23-26d9f7e83169},"Использование",
{1,"ru","Использование"},"",0,0},
...
Этот блок содержит уникальный идентификатор объекта метаданных типа "Реквизит", его имя и синоним.
Блоки коллекций реквизитов, измерений и ресурсов соответствующих объектов метаданных описываются в файле объекта метаданных аналогичным табличным частям образом. Разница заключается только в используемых для этих целей идентификаторах соответствующих коллекций (реквизитов, измерений и ресурсов). См. приложение № 1.
Блок описания реквизита, измерения или ресурса объекта метаданных выглядит следующим образом:
...
{0,0,8361991a-0f30-4a03-9a4c-90556b744f53},"Автор",
{1,"ru","Автор"},"",0,0},
{"Pattern",
{"#",3997c341-4065-4af6-813f-99750a01052b},
{"#",bb356e79-e8e6-4912-8561-ad29cca2604f}
}
...
Этот блок в первых двух своих строках содержит уникальный идентификатор объекта метаданных типа "Реквизит", "Измерение" или "Ресурс", его имя и синоним. При этом идентификатор можно найти в файле DBNames таблицы Params (см. описание файла DBNames):
...
{8361991a-0f30-4a03-9a4c-90556b744f53,"Fld",1499},
...
Далее следует блок описания типов данных реквизита, измерения или ресурса. Начинается он со строки:
...
{"Pattern",
...
Далее следует описание типов данных, примитивных или ссылочных, которые могут использоваться в качестве значений для данного реквизита, измерения или ресурса. Один тип данных - одна строка.
// Описание ссылочного типа данных:
...
{"#",3997c341-4065-4af6-813f-99750a01052b}
...
// Описание строкового типа данных:
...
{"S",256,1}
...
Первое значение такой строки является идентификатором типа данных (см. приложение № 2), а все последующие — квалификаторами типа.
При этом для ссылочных типов данных этот квалификатор является идентификатором объекта метаданных (см. пункт № 1), который расположен во второй строке файла, а не указателем на файл в таблице Config (см. пункт № 2).
Интересно отметить, что для типов данных "ХранилищеЗначения" и "УникальныйИдентификатор" используется строка описания, аналогичная строке описания ссылочного типа данных (# + uuid). Значения uuid для соответствующих типов данных указано в приложении № 2.
Идентификатор |
Объект метаданных |
cf4abea7-37b2-11d4-940f-008048da11f9 |
Коллекция реквизитов справочника |
932159f9-95b2-4e76-a8dd-8849fe5c5ded |
Коллекция табличных частей справочника |
888744e1-b616-11d4-9436-004095e12fc7 |
Коллекция реквизитов табличной части любого объекта метаданных |
45e46cbc-3e24-4165-8b7b-cc98a6f80211 |
Коллекция реквизитов документа |
21c53e09-8950-4b5e-a6a0-1054f1bbc274 |
Коллекция табличных частей документа |
31182525-9346-4595-81f8-6f91a72ebe06 |
Коллекция реквизитов плана вида характеристик |
54e36536-7863-42fd-bea3-c5edd3122fdc |
Коллекция табличных частей плана видов характеристик |
1a1b4fea-e093-470d-94ff-1d2f16cda2ab |
Коллекция реквизитов плана обмена |
52293f4b-f98c-43ea-a80f-41047ae7ab58 |
Коллекция табличных частей плана обмена |
13134203-f60b-11d5-a3c7-0050bae0a776 |
Коллекция измерений регистра сведений |
13134202-f60b-11d5-a3c7-0050bae0a776 |
Коллекция ресурсов регистра сведений |
a2207540-1400-11d6-a3c7-0050bae0a776 |
Коллекция реквизитов регистра сведений |
b64d9a43-1642-11d6-a3c7-0050bae0a776 |
Коллекция измерений регистра накопления |
b64d9a41-1642-11d6-a3c7-0050bae0a776 |
Коллекция ресурсов регистра накопления |
b64d9a42-1642-11d6-a3c7-0050bae0a776 |
Коллекция реквизитов регистра накопления |
6e65cbf5-daa8-4d8d-bef8-59723f4e5777 |
Коллекция реквизитов плана счетов |
78bd1243-c4df-46c3-8138-e147465cb9a4 |
Коллекция признаков учёта плана счетов |
35b63b9d-0adf-4625-a047-10ae874c19a3 |
Коллекция измерений регистра бухгалтерского учёта |
63405499-7491-4ce3-ac72-43433cbe4112 |
Коллекция ресурсов регистра бухгалтерского учёта |
9d28ee33-9c7e-4a1b-8f13-50aa9b36607b |
Коллекция реквизитов регистра бухгалтерского учёта |
Идентификатор |
Объект метаданных |
# |
Ссылка |
S |
Строка |
B |
Булево |
N |
Число |
D |
Дата |
e199ca70-93cf-46ce-a54b-6edc88c3a296 |
ХранилищеЗначения |
fc01b5df-97fe-449b-83d4-218a090e681e |
УникальныйИдентификатор |
public void ParseDBNames()
{
using (Stream stream = GetDBNamesFromDatabase())
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
string line = reader.ReadLine();
while (line != null)
{
line = reader.ReadLine();
}
}
}
public Stream GetDBNamesFromDatabase()
{
SqlBytes binaryData = SelectDBNamesFromDatabase();
if (binaryData == null) return null;
return new DeflateStream(binaryData.Stream, CompressionMode.Decompress);
}
public SqlBytes SelectDBNamesFromDatabase()
{
SqlBytes binaryData = null;
{
SqlConnection connection = new SqlConnection(ConnectionString);
SqlCommand command = connection.CreateCommand();
SqlDataReader reader = null;
command.CommandType = CommandType.Text;
command.CommandText = "SELECT [BinaryData] FROM [Params] WHERE [FileName] = N'DBNames'";
try
{
connection.Open();
reader = command.ExecuteReader();
if (reader.Read())
{
binaryData = reader.GetSqlBytes(0);
}
reader.Close();
}
catch { throw; }
finally { DisposeDatabaseResources(connection, command, reader); }
}
return binaryData;
}
Пример использования:
Алгоритм чтения метаданных (см. исходный код на GitHub):
1. Читаем файл DBNames из таблицы Params.
2. Используя файл DBNames, читаем файлы объектов метаданных из таблицы Config.
3. Дополняем объекты метаданных недостающими стандартными реквизитами (их нет в файлах объектов метаданных). Это можно сделать, например, выполняя чтение полей таблиц SQL Server (INFORMATION_SCHEMA.COLUMNS). Эти поля имеют стандартные и достаточно понятные имена. Как они называются в 1С мы тоже знаем. Например, "_Description" это "Наименование" справочника.
Более подробная версия статьи доступна по ссылке:
https://github.com/zhichkin/dajet/blob/main/doc/metadata-internals/README.md
Пример чтения метаданных 1С, например, для генерации представлений (view) базы данных можно посмотреть в проекте dajet-dbview-generator репозитория платформы DaJet на GitHub.
Выпущена новая версия библиотеки DaJet.Metadata 4.0.0.
Выкладывать пакет на NuGet пока не планирую ¯\_(|84;)_/¯
Новая версия проекта прошла все тесты на чтение метаданных конфигураций БП и УТ.
Скорость чтения метаданных для этих конфигураций составляет приблизительно 500 мс (0.5 секунды).
Проект переведён на .NET 6.0
Выпуск нового пакета NuGet планируется в ближайшие месяц-два - нужно "причесать" API использования.
Как и в старой версии DaJet.Metadata 3.2.0 поддерживаются следующие объекты конфигурации:
- Свойства конфигурации
- Общие реквизиты
- Определяемые типы
- Перечисления
- Справочники
- Документы
- Планы обмена
- Планы видов характеристик
- Регистры сведений
- Регистры накопления
Планы развития:
1. Поддержка новых объектов метаданных:
- Константы
- Подсистемы
- Бизнес-процессы
- Планы счетов бухгалтерии
2. Сравнение двух конфигураций между собой.
3. Сохранение метаданных в отдельную базу данных.
Большинство из этих алгоритмов уже реализовано - требуется только оформить в библиотеке в виде удобного API.
Новая версия проекта имеет следующие преимущества:
- Новый более эффективный и точный парсер файлов метаданных 1С:Предприятие 8.
- Парсер более удобен для программного использования: читает файл метаданных как поток токенов.
- Возможность выборочной загрузки объектов метаданных по их имени или UUID, а не всей конфигурации с последующим поиском нужного объекта. Загрузка метаданных регистра сведений, например, занимает таким образом 2-3 миллисекунды.
- Более подробная документация для написания парсеров на своём любимом языке программирования.
- Добавлен класс ConfigFileWriter для сохранения файлов конфигурации в удобном для анализа формате.
В данном случае будут прочитаны файлы "root", основной файл описания конфигурации (только ветка со списком uuid'ов регистров сведений) и файлы описания регистров сведений. При этом чтение файлов регистров сведений будет прерываться сразу же как только будет установлено неравенство с искомым именем объекта метаданных. При совпадении имени нужный файл будет прочитан целиком. После этого чтение метаданных прекратится. Такой алгоритм позволяет загружать искомые объекты метаданных за считанные миллисекунды.
Кроме этого результаты чтения файла "root" и основного файла описания конфигурации могут быть закэшированы.
// Читаем uuid основного файла описания конфигурации
Guid root;
using (ConfigFileReader reader = new ConfigFileReader(
DatabaseProvider.SQLServer, MS_CONNECTION_STRING, ConfigTableNames.Config, "root"))
{
root = new RootFileParser().Parse(in reader);
}
// Ссылка на объект метаданных (в данном примере это регистр сведений)
MetadataObject target;
// Имя объекта метаданных, как оно задано в конфигураторе
string name = "ЦеныНоменклатуры";
using (ConfigFileReader reader = new ConfigFileReader(
DatabaseProvider.SQLServer, MS_CONNECTION_STRING, ConfigTableNames.Config, root))
{
new InfoBaseParser().ParseByName(in reader, MetadataRegistry.InformationRegisters, in name , out target);
}
if (target == null)
{
Console.WriteLine($"Объект метаданных {name} не найден.");
}
else
{
Console.WriteLine($"Объект метаданных {name} {{{target.Uuid}}} найден и загружен успешно.");
}
public void WriteRootConfigToFile()
{
Guid root;
using (ConfigFileReader reader = new ConfigFileReader(
DatabaseProvider.SQLServer, MS_CONNECTION_STRING, ConfigTableNames.Config, "root"))
{
root = new RootFileParser().Parse(in reader);
}
ConfigObject config;
using (ConfigFileReader reader = new ConfigFileReader(
DatabaseProvider.SQLServer, MS_CONNECTION_STRING, ConfigTableNames.Config, root))
{
config = new ConfigFileParser().Parse(in reader);
}
new ConfigFileWriter().Write(config, "C:\\dump-1c\\config.txt");
}
Ожидаемый вывод может быть, например, таким:
[0] (0) "2"
[0] (1) DaJet.Metadata.Model.ConfigObject
----[1] (1.0) "684c8f2b-d93f-49cc-b766-b3cc3896b047"
[0] (2) "7"
[0] (3) DaJet.Metadata.Model.ConfigObject
----[1] (3.0) "9cd510cd-abfc-11d4-9434-004095e12fc7"
----[1] (3.1) DaJet.Metadata.Model.ConfigObject
--------[2] (3.1.0) "1"
--------[2] (3.1.1) DaJet.Metadata.Model.ConfigObject
------------[3] (3.1.1.0) "62"
------------[3] (3.1.1.1) DaJet.Metadata.Model.ConfigObject
----------------[4] (3.1.1.1.0) "0"
----------------[4] (3.1.1.1.1) DaJet.Metadata.Model.ConfigObject
--------------------[5] (3.1.1.1.1.0) "3"
--------------------[5] (3.1.1.1.1.1) DaJet.Metadata.Model.ConfigObject
------------------------[6] (3.1.1.1.1.1.0) "1"
------------------------[6] (3.1.1.1.1.1.1) "0"
------------------------[6] (3.1.1.1.1.1.2) "db425e45-1ec5-45ba-b5e9-e0a059301888"
--------------------[5] (3.1.1.1.1.2) "dajet_metadata"
--------------------[5] (3.1.1.1.1.3) DaJet.Metadata.Model.ConfigObject
------------------------[6] (3.1.1.1.1.3.0) "1"
------------------------[6] (3.1.1.1.1.3.1) "ru"
------------------------[6] (3.1.1.1.1.3.2) "DaJet Metadata"
--------------------[5] (3.1.1.1.1.4) "Тестовая ИБ для чтения метаданных 1С"
--------------------[5] (3.1.1.1.1.5) "0"
--------------------[5] (3.1.1.1.1.6) "0"
--------------------[5] (3.1.1.1.1.7) "00000000-0000-0000-0000-000000000000"
--------------------[5] (3.1.1.1.1.8) "0"
// Идентификатор объекта метаданных - имя его файла, поля FileName, в таблице Config
Guid uuid = new Guid("f6d7a041-3a57-457c-b303-ff888c9e98b7");
using (ConfigFileReader reader = new ConfigFileReader(
DatabaseProvider.SQLServer, MS_CONNECTION_STRING, ConfigTableNames.Config, uuid))
{
while (reader.Read()) // Читаем файл до конца
{
if (reader.Token == TokenType.StartFile)
{
// Обрабатываем начало файла
}
else if (reader.Token == TokenType.StartObject)
{
// Обрабатываем начало объекта метаданных
}
else if (reader.Token == TokenType.Value)
{
// Обрабатываем не строковое значение (число, uuid и т.д.)
}
else if (reader.Token == TokenType.String)
{
// Обрабатываем строковое значение
}
else if (reader.Token == TokenType.EndObject)
{
// Обрабатываем конец объекта метаданных
}
else if (reader.Token == TokenType.EndFile)
{
// Обрабатываем конец файла
}
}
}
Для удобства написания специализированных парсеров, например, структуры объекта "ОписаниеТипов", входящей в описание реквизитов объектов метаданных, реализованы вспомогательные классы. Это даёт возможность реализовывать вложенные друг в друга парсеры. Вспомогательные классы ConfigFileParser и ConfigFileConverter таким образом дополняют основной класс ConfigFileReader.
1. Пример структуры файла:
{1,{2,"Привет, 1С!",3}}
2. Структура файла, выраженная в формате DaJet.Metadata (спасибо классу ConfigFileWriter):
[0] (0) "1"
[0] (1) DaJet.Metadata.Model.ConfigObject
----[1] (1.0) "2"
----[1] (1.1) "Привет, 1С!"
----[1] (1.2) "3"
3. Пример класса парсера для этой структуры:
public sealed class HelloParser
{
private ConfigFileParser _parser = new ConfigFileParser();
private ConfigFileConverter _converter = new ConfigFileConverter();
public int Значение1 { get; set; }
public int Значение2 { get; set; }
public int Значение3 { get; set; }
public int Hello { get; set; }
public void Parse(in ConfigFileReader reader)
{
// Настраиваем конвертер значений файла по известным нам путям
// Пути к значениям берём из файла в формате DaJet.Metadata
_converter[0] += ОбработатьЗначение1;
_converter[1][0] += ОбработатьЗначение2;
_converter[1][1] += ОбработатьHello;
_converter[1][2] += ОбработатьЗначение3;
// Выполняем последовательное чтение файла с вызовом указанных обработчиков
_parser.Parse(in reader, in _converter);
}
private void ОбработатьЗначение1(in ConfigFileReader source, in CancelEventArgs args)
{
Значение1 = source.GetInt32();
}
private void ОбработатьЗначение2(in ConfigFileReader source, in CancelEventArgs args)
{
Значение2 = source.GetInt32();
}
private void ОбработатьЗначение3(in ConfigFileReader source, in CancelEventArgs args)
{
Значение3 = source.GetInt32();
}
private void ОбработатьHello(in ConfigFileReader source, in CancelEventArgs args)
{
Hello = source.Value;
}
}
4. Пример использования такого парсера:
HelloParser parser = new HelloParser();
using (ConfigFileReader reader = new ConfigFileReader(
DatabaseProvider.SQLServer, MS_CONNECTION_STRING, ConfigTableNames.Config, "hello"))
{
parser.Parse(in reader);
}
Console.WriteLine($"Hello = {parser.Hello}");
Console.WriteLine($"Значение 1 = {parser.Значение1}");
Console.WriteLine($"Значение 2 = {parser.Значение2}");
Console.WriteLine($"Значение 3 = {parser.Значение3}");
// Ожидаемый вывод в консоль:
//
// Hello = Привет, 1С!
// Значение 1 = 1
// Значение 2 = 2
// Значение 3 = 3
Пример самого простого парсера (читает UUID конфигурации из файла 'root'): RootFileParser.
Пример сложного вложенного парсера (читает коллекцию реквизитов объекта метаданных): MetadataPropertyCollectionParser.
Начал работу над проектом генерации JSON Schema для конфигураций на платформе 1С:Предприятие 8.
Полезно для интеграции с внешними не-1С системами.
Исходный код C# на GitHub: dajet-metadata-schema
Класс Configurator, метод OpenInfoBase.
См. также диаграмму в заголовке публикации.
1. Создаётся новый объект класса InfoBase.
2. Загружается файл DBNames из таблицы Params. Файл DBNames содержит следующую информацию:
- FileName (uuid)
- TypeToken (Reference, VT, Fld и т.д.)
- Code (int)
3. Из файла DBNames заполняются словари Properties, TableParts и AllTypes объекта InfoBase. Ключом словаря является FileName, а значением, в зависимости от TypeToken, является объект классов ApplicationObject или MetadataProperty.
4. Загружается файл root из таблицы Config. Файл root содержит ссылку (uuid) на файл описания состава конфигурации (дерева конфигурации). Условно назовём этот файл config.
5. Из файла config в объект InfoBase загружаются основные свойства конфигурации, например, наименование, версия, режимы работы различных аспектов конфигурации.
6. Из файла config в объект InfoBase загружаются следующие объекты метаданных из ветки "Общие" дерева конфигурации:
- Общие реквизиты
- Определяемые типы
Заполняются словари SharedProperties и NamedDataTypeSets. Ключом словарей являются uuid этих объектов, а значениями объекты классов SharedProperty и NamedDataTypeSet.
Объект SharedProperty содержит правила применения общего реквизита для различных прикладных объектов метаданных. Правила применения ссылаются на соответствующие объекты метаданных при помощи FileName.
Объект NamedDataTypeSet идентифицируется по uuid и содержит именованный набор типов данных, применяемый к свойствам различных прикладных объектов метаданных. Ссылка на объект NamedDataTypeSet (uuid) содержится в свойстве PropertyType объекта MetadataProperty.
7. Выполняется загрузка прикладных объектов метаданных в циклах по соответствующим коллекциям объекта InfoBase. Поиск соответствующих файлов в таблице Config осуществляется по FileName.
Свойства (реквизиты, измерения и ресурсы) объектов метаданных, а также их табличных частей, как и сами табличные части, идентифицируются по uuid и сопоставляются с файлом DBNames по FileName, который был ранее загружен в словари Properties и TableParts объекта InfoBase.
Ссылочные типы данных свойств, которые указываются в свойстве PropertyType объекта MetadataProperty, сопоставляются по их uuid, которые были получены в ходе загрузки соответствующих файлов таблицы Config по FileName. В данном случае FileName и идентификатор типа объекта метаданных (uuid) это разные значения. Скорее всего это идентификатор типа, например, "СправочникСсылка.Номенклатура". В отличие от, например, идентификатора типа "СправочникОбъект.Номенклатура".
При указании типом данных свойства "Харакетристика" выполняется поиск соответствующего объекта типа "План видов харакетристик", однако в данном случае uuid и typeUuid (DataTypeSetUuid) для плана видов характеристик это разные значения. Оба эти значения загружаются из соответствующего файла таблицы Config по FileName.
Скорее всего uuid – это тип данных "ПланВидовХаракетристикСсылка", а uuidType – "ОписаниеХарактеристик".
При указании типом данных свойства "Определяемый тип" выполняется поиск соответствующего определяемого типа по его идентификатору uuid (см. описание NamedDataTypeSet выше).
Кроме этого существуют специальные идентификаторы uuid для конкретных типов данных:
- ХранилищеЗначения;
- УникальныйИдентификатор.
А также для обобщённых типов данных:
- ЛюбаяСсылка;
- СправочникСсылка;
- и т.д.
При указании обобщённого типа, например, ДокументСсылка необходимо проверять количество объектов метаданных данного типа в конфигурации, так как если существует только один документ, то значение свойства не может быть составным типом и наоборот.
8. Идентификаторы FileName владельцев справочников содержатся в файле подчинённого объекта метаданных (справочника), который загружается из таблицы Config по FileName.
9. Идентификаторы FileName регистров, по которым выполняются движения, хранятся в файлах соответствующих объектов метаданных (документов). Таким образом конфигурация свойства "Регистратор" регистров накопления и регистров сведений, подчинённых регистратору, выполняется по мере загрузки файлов документов.
Добавлено описание методики исследования файлов объектов метаданных на GitHub.
Добавлена поддержка PostgreSQL.