private void 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 = _propDictItemSearchService.Search(new PropertyDictionaryItemSearchCriteria { PropertyIds = allDictPropertyIds, Take = int.MaxValue }).Results; foreach (var dictPropValue in csvProducts.SelectMany(x => x.PropertyValues).Where(x => x.Property != null && x.Property.Dictionary && !string.IsNullOrEmpty(x.Value?.ToString()))) { dictPropValue.Alias = dictPropValue.Value.ToString(); var existDictItem = allDictItems.FirstOrDefault(x => x.PropertyId == dictPropValue.Property.Id && x.Alias.EqualsInvariant(dictPropValue.Alias)); if (existDictItem == null) { if (_createPropertyDictionatyValues) { existDictItem = new PropertyDictionaryItem { Alias = dictPropValue.Alias, PropertyId = dictPropValue.Property.Id }; allDictItems.Add(existDictItem); _propDictItemService.SaveChanges(new[] { existDictItem }); } else { progressInfo.Errors.Add($"The property dictionary '{dictPropValue.Alias}' not found in '{dictPropValue.Property.Name}' dictionary"); progressCallback(progressInfo); } } dictPropValue.ValueId = existDictItem?.Id; } }
public IHttpActionResult SaveChanges(moduleModel.PropertyDictionaryItem[] propertyDictItems) { _propertyDictionaryService.SaveChanges(propertyDictItems); return(Ok()); }
public void DoImport(Stream stream, PlatformExportManifest manifest, Action <ExportImportProgressInfo> progressCallback) { var progressInfo = new ExportImportProgressInfo(); var productsTotalCount = 0; var propDictItemTotalCount = 0; var propertiesWithForeignKeys = new List <Property>(); using (var streamReader = new StreamReader(stream)) using (var reader = new JsonTextReader(streamReader)) { while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName) { if (reader.Value.ToString() == "Catalogs") { reader.Read(); var catalogs = _serializer.Deserialize <Catalog[]>(reader); progressInfo.Description = $"{ catalogs.Count() } catalogs are importing…"; progressCallback(progressInfo); _catalogService.Update(catalogs); } else if (reader.Value.ToString() == "Categories") { reader.Read(); var categories = _serializer.Deserialize <Category[]>(reader); progressInfo.Description = $"{ categories.Count() } categories are importing…"; progressCallback(progressInfo); _categoryService.Update(categories); if (manifest.HandleBinaryData) { ImportImages(categories, progressInfo); } } else if (reader.Value.ToString() == "Properties") { reader.Read(); var properties = _serializer.Deserialize <Property[]>(reader); foreach (var property in properties) { 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; } } progressInfo.Description = $"{ properties.Count() } properties are importing…"; progressCallback(progressInfo); _propertyService.Update(properties); } else if (reader.Value.ToString() == "ProductsTotalCount") { productsTotalCount = reader.ReadAsInt32() ?? 0; } else if (reader.Value.ToString() == "PropertyDictionaryItemsTotalCount") { propDictItemTotalCount = reader.ReadAsInt32() ?? 0; } else if (reader.Value.ToString() == "PropertyDictionaryItems") { reader.Read(); if (reader.TokenType == JsonToken.StartArray) { reader.Read(); var propDictItems = new List <PropertyDictionaryItem>(); var propDictItemsCount = 0; //Import property dcitonary items while (reader.TokenType != JsonToken.EndArray) { var propDictItem = AbstractTypeFactory <PropertyDictionaryItem> .TryCreateInstance(); propDictItem = _serializer.Deserialize(reader, propDictItem.GetType()) as PropertyDictionaryItem; propDictItems.Add(propDictItem); propDictItemsCount++; reader.Read(); if (propDictItemsCount % BatchSize == 0 || reader.TokenType == JsonToken.EndArray) { _propertyDictionaryService.SaveChanges(propDictItems.ToArray()); propDictItems.Clear(); if (propDictItemsCount > 0) { progressInfo.Description = $"{ propDictItemsCount } of { propDictItemTotalCount } dictionary items have been imported"; } else { progressInfo.Description = $"{ propDictItemsCount } dictionary items have been imported"; } progressCallback(progressInfo); } } } } else if (reader.Value.ToString() == "Products") { reader.Read(); if (reader.TokenType == JsonToken.StartArray) { reader.Read(); var associationBackupMap = new Dictionary <string, ICollection <ProductAssociation> >(); var products = new List <CatalogProduct>(); var productsCount = 0; //Import products while (reader.TokenType != JsonToken.EndArray) { var product = AbstractTypeFactory <CatalogProduct> .TryCreateInstance(); product = _serializer.Deserialize(reader, product.GetType()) as CatalogProduct; //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); productsCount++; reader.Read(); if (productsCount % BatchSize == 0 || reader.TokenType == JsonToken.EndArray) { _itemService.Update(products.ToArray()); if (manifest.HandleBinaryData) { ImportImages(products.ToArray(), progressInfo); } products.Clear(); if (productsTotalCount > 0) { progressInfo.Description = $"{ productsCount } of { productsTotalCount } products have been imported"; } else { progressInfo.Description = $"{ productsCount } products have been imported"; } progressCallback(progressInfo); } } //Import products associations separately to avoid DB constrain violation var totalProductsWithAssociationsCount = associationBackupMap.Count; progressInfo.Description = $"{ totalProductsWithAssociationsCount } products associations are importing…"; progressCallback(progressInfo); 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); } _associationService.SaveChanges(fakeProducts.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) { _propertyService.Update(propertiesWithForeignKeys.Skip(i).Take(BatchSize).ToArray()); progressInfo.Description = $"{ Math.Min(totalCount, i + BatchSize) } of { totalCount } property associations updated."; progressCallback(progressInfo); } } }