private static void AddLanguages(Item item, ItemsLanguagesData languagesData)
        {
            var languages = new ItemLanguagesData();

            languagesData.Add(item.ID, languages);

            foreach (var pair in item.Fields.Unversioned)
            {
                var          languageName = pair.Key;
                VersionsData languageFields;
                if (!languages.TryGetValue(languageName, out languageFields))
                {
                    languageFields = new VersionsData();
                    languages.Add(languageName, languageFields);
                }

                var unversionedFields = languageFields.TryGetValue(0);
                if (unversionedFields == null)
                {
                    unversionedFields = new FieldsData();
                    languageFields.Add(0, unversionedFields);
                }

                foreach (var field in pair.Value.OrderBy(x => Guid.Parse(x.Key)).ToArray())
                {
                    unversionedFields.Add(Guid.Parse(field.Key), field.Value);
                }
            }

            foreach (var pair in item.Fields.Versioned)
            {
                var          languageName = pair.Key;
                VersionsData languageFields;
                if (!languages.TryGetValue(languageName, out languageFields))
                {
                    languageFields = new VersionsData();
                    languages.Add(languageName, languageFields);
                }

                foreach (var versionPair in pair.Value)
                {
                    var versionNumber = versionPair.Key;
                    var version       = languageFields.TryGetValue(versionNumber);
                    if (version == null)
                    {
                        version = new FieldsData();
                        languageFields.Add(versionNumber, version);
                    }

                    var versionFields = versionPair.Value
                                        .Select(x => CreatePair(Guid.Parse(x.Key), x.Value))
                                        .OrderBy(x => x.Key);

                    foreach (var field in versionFields)
                    {
                        version.Add(field.Key, field.Value);
                    }
                }
            }
        }
        public void Execute()
        {
            Assert.ArgumentNotNullOrEmpty(ConnectionString, nameof(ConnectionString));
            Assert.ArgumentNotNullOrEmpty(DatabaseName, nameof(DatabaseName));
            Assert.ArgumentNotNullOrEmpty(OutputDirectory, nameof(OutputDirectory));
            Assert.ArgumentCondition(Directory.Exists(OutputDirectory), nameof(OutputDirectory), $"The specified directory does not exist: {OutputDirectory}");
            Assert.ArgumentCondition(Try(() => new SqlConnectionStringBuilder(ConnectionString)), nameof(ConnectionString), "$The specified connection string");

            using (var definitionsWriter = File.OpenWrite(Path.Combine(OutputDirectory, $"{DatabaseName}.items.dat")))
            {
                var definitions        = new ItemDefinitions();
                var itemsSharedData    = new ItemsSharedData();
                var itemsLanguagesData = new ItemsLanguagesData();

                var context = ItemManager.Initialize(ConnectionString);

                var counter = 0;
                Console.WriteLine("Processing items...");
                foreach (var item in GetItems(context))
                {
                    // definition
                    AddDefinition(item, definitions);

                    // shared fields
                    AddShared(item, itemsSharedData);

                    // unversioned and versioned-1 fields
                    AddLanguages(item, itemsLanguagesData);

                    Console.WriteLine($"{++counter:D5}. {GetItemPath(definitions, item.ID)}");
                }

                Console.WriteLine("Serializing...");
                Serializer.Serialize(definitionsWriter, new ItemsData
                {
                    Definitions  = definitions,
                    SharedData   = itemsSharedData,
                    LanguageData = itemsLanguagesData
                });
            }
        }