Exemplo n.º 1
0
        private async Task ResolvePropertyDictionaryItems(List <CsvProduct> csvProducts, ExportImportProgressInfo progressInfo, Action <ExportImportProgressInfo> progressCallback)
        {
            var allDictPropertyIds = csvProducts.SelectMany(x => x.Properties).Where(x => x.Dictionary)
                                     .Select(x => x.Id).Distinct()
                                     .ToArray();

            var allDictItems = (await _propDictItemSearchService.SearchAsync(new PropertyDictionaryItemSearchCriteria
            {
                PropertyIds = allDictPropertyIds,
                Take = int.MaxValue
            })).Results;

            foreach (var dictProperty in csvProducts.SelectMany(x => x.Properties).Where(x => x.Dictionary && x.Values?.Any(v => v != null) == true))
            {
                foreach (var propertyValue in dictProperty.Values.Where(x => x.Value != null))
                {
                    // VP-5516:
                    // For imported propertyValue the Alias field is empty - need to fill it from value.
                    // For existing propertyValue Alias should be already filled, we shouldn't rewrite it.
                    propertyValue.Alias = string.IsNullOrEmpty(propertyValue.Alias) ? propertyValue.Value.ToString() : propertyValue.Alias;

                    var existentDictItem = allDictItems.FirstOrDefault(x => x.PropertyId == propertyValue.PropertyId && x.Alias.EqualsInvariant(propertyValue.Alias));

                    if (existentDictItem == null)
                    {
                        if (CreatePropertyDictionatyValues)
                        {
                            existentDictItem = new PropertyDictionaryItem
                            {
                                Alias      = propertyValue.Alias,
                                PropertyId = propertyValue.PropertyId
                            };
                            allDictItems.Add(existentDictItem);
                            await _propDictItemService.SaveChangesAsync(new[] { existentDictItem });
                        }
                        else
                        {
                            progressInfo.Errors.Add($"The '{propertyValue.Alias}' dictionary item is not found in '{propertyValue.PropertyName}' dictionary");
                            progressCallback(progressInfo);
                        }
                    }
                    propertyValue.ValueId = existentDictItem?.Id;
                }
            }
        }
Exemplo n.º 2
0
        public async Task <ActionResult> SaveChanges([FromBody] PropertyDictionaryItem[] propertyDictItems)
        {
            await _propertyDictionaryService.SaveChangesAsync(propertyDictItems);

            return(Ok());
        }
        public async Task DoImportAsync(Stream inputStream, ExportImportOptions options, Action <ExportImportProgressInfo> progressCallback,
                                        ICancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var progressInfo = new ExportImportProgressInfo();
            var propertiesWithForeignKeys = new List <Property>();

            using (var streamReader = new StreamReader(inputStream))
                using (var reader = new JsonTextReader(streamReader))
                {
                    while (reader.Read())
                    {
                        if (reader.TokenType == JsonToken.PropertyName)
                        {
                            if (reader.Value.ToString() == "Catalogs")
                            {
                                await reader.DeserializeJsonArrayWithPagingAsync <Catalog>(_jsonSerializer, _batchSize, async (items) =>
                                {
                                    await _catalogService.SaveChangesAsync(items.ToArray());
                                }, processedCount =>
                                {
                                    progressInfo.Description = $"{ processedCount } catalogs have been imported";
                                    progressCallback(progressInfo);
                                }, cancellationToken);
                            }
                            else if (reader.Value.ToString() == "Categories")
                            {
                                await reader.DeserializeJsonArrayWithPagingAsync <Category>(_jsonSerializer, _batchSize, async (items) =>
                                {
                                    var itemsArray = items.ToArray();
                                    await _categoryService.SaveChangesAsync(itemsArray);
                                    ImportImages(itemsArray.OfType <IHasImages>().ToArray(), progressInfo);
                                }, processedCount =>
                                {
                                    progressInfo.Description = $"{ processedCount } categories have been imported";
                                    progressCallback(progressInfo);
                                }, cancellationToken);
                            }
                            else if (reader.Value.ToString() == "Properties")
                            {
                                await reader.DeserializeJsonArrayWithPagingAsync <Property>(_jsonSerializer, _batchSize, async (items) =>
                                {
                                    var itemsArray = items.ToArray();
                                    foreach (var property in itemsArray)
                                    {
                                        if (property.CategoryId != null || property.CatalogId != null)
                                        {
                                            propertiesWithForeignKeys.Add(property.Clone() as Property);
                                            //Need to reset property foreign keys to prevent FK violation during  inserting into database
                                            property.CategoryId = null;
                                            property.CatalogId  = null;
                                        }
                                    }
                                    await _propertyService.SaveChangesAsync(itemsArray);
                                }, processedCount =>
                                {
                                    progressInfo.Description = $"{ processedCount } properties have been imported";
                                    progressCallback(progressInfo);
                                }, cancellationToken);
                            }
                            else if (reader.Value.ToString() == "PropertyDictionaryItems")
                            {
                                await reader.DeserializeJsonArrayWithPagingAsync <PropertyDictionaryItem>(_jsonSerializer, _batchSize, items => _propertyDictionaryService.SaveChangesAsync(items.ToArray()), processedCount =>
                                {
                                    progressInfo.Description = $"{ processedCount } property dictionary items have been imported";
                                    progressCallback(progressInfo);
                                }, cancellationToken);
                            }
                            else if (reader.Value.ToString() == "Products")
                            {
                                var associationBackupMap = new Dictionary <string, IList <ProductAssociation> >();
                                var products             = new List <CatalogProduct>();

                                await reader.DeserializeJsonArrayWithPagingAsync <CatalogProduct>(_jsonSerializer, _batchSize, async (items) =>
                                {
                                    var itemsArray = items.ToArray();
                                    foreach (var product in itemsArray)
                                    {
                                        //Do not save associations withing product to prevent dependency conflicts in db
                                        //we will save separateley after product import
                                        if (!product.Associations.IsNullOrEmpty())
                                        {
                                            associationBackupMap[product.Id] = product.Associations;
                                        }

                                        product.Associations = null;
                                        products.Add(product);
                                    }
                                    await _itemService.SaveChangesAsync(products.ToArray());
                                    if (options != null && options.HandleBinaryData)
                                    {
                                        ImportImages(itemsArray.OfType <IHasImages>().ToArray(), progressInfo);
                                    }

                                    products.Clear();
                                }, processedCount =>
                                {
                                    progressInfo.Description = $"{ processedCount } products have been imported";
                                    progressCallback(progressInfo);
                                }, cancellationToken);

                                //Import products associations separately to avoid DB constrain violation
                                var totalProductsWithAssociationsCount = associationBackupMap.Count;
                                for (var i = 0; i < totalProductsWithAssociationsCount; i += _batchSize)
                                {
                                    var fakeProducts = new List <CatalogProduct>();
                                    foreach (var pair in associationBackupMap.Skip(i).Take(_batchSize))
                                    {
                                        var fakeProduct = AbstractTypeFactory <CatalogProduct> .TryCreateInstance();

                                        fakeProduct.Id           = pair.Key;
                                        fakeProduct.Associations = pair.Value;
                                        fakeProducts.Add(fakeProduct);
                                    }

                                    await _associationService.SaveChangesAsync(fakeProducts.OfType <IHasAssociations>().ToArray());

                                    progressInfo.Description = $"{ Math.Min(totalProductsWithAssociationsCount, i + _batchSize) } of { totalProductsWithAssociationsCount } products associations imported";
                                    progressCallback(progressInfo);
                                }
                            }
                        }
                    }
                }

            //Update property associations after all required data are saved (Catalogs and Categories)
            if (propertiesWithForeignKeys.Count > 0)
            {
                progressInfo.Description = $"Updating {propertiesWithForeignKeys.Count} property associations…";
                progressCallback(progressInfo);

                var totalCount = propertiesWithForeignKeys.Count;
                for (var i = 0; i < totalCount; i += _batchSize)
                {
                    await _propertyService.SaveChangesAsync(propertiesWithForeignKeys.Skip(i).Take(_batchSize).ToArray());

                    progressInfo.Description = $"{ Math.Min(totalCount, i + _batchSize) } of { totalCount } property associations updated.";
                    progressCallback(progressInfo);
                }
            }
        }
Exemplo n.º 4
0
 private async Task ImportPropertyDictionaryItemsAsync(JsonTextReader reader, ExportImportProgressInfo progressInfo, Action <ExportImportProgressInfo> progressCallback, ICancellationToken cancellationToken)
 {
     await reader.DeserializeJsonArrayWithPagingAsync <PropertyDictionaryItem>(_jsonSerializer, _batchSize, items => _propertyDictionaryService.SaveChangesAsync(items.ToArray()), processedCount =>
     {
         progressInfo.Description = $"{ processedCount } property dictionary items have been imported";
         progressCallback(progressInfo);
     }, cancellationToken);
 }