public async Task <List <ImportedEntityDetails <Ingredient, IParsableImportEntity <Ingredient> > > > ExtractAsync()
        {
            var importDetails = new List <ImportedEntityDetails <Ingredient, IParsableImportEntity <Ingredient> > >();

            for (int i = _fromId; i <= _toId; ++i)
            {
                var currentUrl = _getIngredientUrl.Replace(_idPlaceholder, i.ToString());
                var result     = await _httpClient.GetAsync(currentUrl);

                result.EnsureSuccessStatusCode();

                var json = await result.Content.ReadAsStringAsync();

                var dto = JsonConvert.DeserializeObject <IngredientsRootDto>(json);
                if (dto.Ingredients.IsNullOrEmpty())
                {
                    _logger.Warning($"Ingredient import result (ID: {i}) - Not found");
                    continue;
                }
                var sourceIngredient = dto.Ingredients[0];
                var ingredient       = sourceIngredient.ParseToEntity();
                var detail           = new ImportedEntityDetails <Ingredient, IParsableImportEntity <Ingredient> >(ingredient, sourceIngredient);
                importDetails.Add(detail);

                _logger.Information($"Ingredient import result (ID: {i}) - {ingredient.Name}");
            }
            return(importDetails);
        }
        public async Task <List <ImportedEntityDetails <Drink, IParsableImportEntity <Drink> > > > ExtractAsync(List <ImportedEntityDetails <Ingredient, IParsableImportEntity <Ingredient> > > importedIngredients)
        {
            var importDetails      = new List <ImportedEntityDetails <Drink, IParsableImportEntity <Drink> > >();
            int failedImportsCount = 0;

            for (int i = _fromId; i <= _toId; ++i)
            {
                var currentUrl = _getDrinkUrl.Replace(_idPlaceholder, i.ToString());
                var result     = await _httpClient.GetAsync(currentUrl);

                result.EnsureSuccessStatusCode();

                var json = await result.Content.ReadAsStringAsync();

                var dto = JsonConvert.DeserializeObject <DrinksRootDto>(json);
                if (dto.Drinks.IsNullOrEmpty())
                {
                    _logger.Warning($"Drink import result (ID: {i}) - Not found");
                    continue;
                }

                NormalizedDrinkRecord sourceDrink;
                try
                {
                    sourceDrink = dto.Drinks[0].Normalize();
                }
                catch (NormalizeIngredientException e)
                {
                    _logger.Warning(e.Message);
                    ++failedImportsCount;
                    continue;
                }

                if (!TryMapIngredientsToBusinessEntities(sourceDrink, importedIngredients))
                {
                    continue;
                }

                var drink  = sourceDrink.ParseToEntity();
                var detail = new ImportedEntityDetails <Drink, IParsableImportEntity <Drink> >(drink, sourceDrink);
                importDetails.Add(detail);

                _logger.Information($"Drink import result (ID: {i}) - {drink.Name}");
            }
            if (failedImportsCount > 0)
            {
                _logger.Warning($"{failedImportsCount} Cocktails couldn't be parsed from the database");
            }

            _logger.Information($"{importDetails.Count} Cocktails could be parsed from the database");

            return(importDetails);
        }