public void DoImport(Stream stream, PlatformExportManifest manifest, Action <ExportImportProgressInfo> progressCallback) { var progressInfo = new ExportImportProgressInfo(); var productsTotalCount = 0; using (StreamReader streamReader = new StreamReader(stream)) using (JsonTextReader 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 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 importing..."; progressCallback(progressInfo); _categoryService.Update(categories); if (manifest.HandleBinaryData) { ImportImages(categories); } } else if (reader.Value.ToString() == "Properties") { reader.Read(); var properties = _serializer.Deserialize <Property[]>(reader); progressInfo.Description = $"{ properties.Count() } properties importing..."; progressCallback(progressInfo); _propertyService.Update(properties); } else if (reader.Value.ToString() == "ProductsTotalCount") { productsTotalCount = reader.ReadAsInt32() ?? 0; } 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 = _serializer.Deserialize <CatalogProduct>(reader); //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()); } products.Clear(); if (productsTotalCount > 0) { progressInfo.Description = $"{ productsCount } of { productsTotalCount } products imported"; } else { progressInfo.Description = $"{ productsCount } products imported"; } progressCallback(progressInfo); } } //Import products associations separately to avoid DB constrain violation var totalProductsWithAssociationsCount = associationBackupMap.Count(); progressInfo.Description = $"{ totalProductsWithAssociationsCount } products associations importing..."; progressCallback(progressInfo); for (int i = 0; i < totalProductsWithAssociationsCount; i += _batchSize) { var fakeProducts = new List <CatalogProduct>(); foreach (var pair in associationBackupMap.Skip(i).Take(_batchSize)) { var fakeProduct = new CatalogProduct { Id = pair.Key, Associations = pair.Value }; fakeProducts.Add(fakeProduct); } _associationService.SaveChanges(fakeProducts.ToArray()); progressInfo.Description = $"{ Math.Min(totalProductsWithAssociationsCount, i + _batchSize) } of { totalProductsWithAssociationsCount } products associations imported"; progressCallback(progressInfo); } } } } } } }
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); } } }