public void Init(IImportExecuteContext context, DataExchangeSettings dataExchangeSettings) { UtcNow = DateTime.UtcNow; DownloadedItems = new Dictionary <string, string>(); ImageDownloadFolder = Path.Combine(context.ImportFolder, _imageDownloadFolder); if (dataExchangeSettings.ImageImportFolder.HasValue()) { ImageFolder = Path.Combine(context.ImportFolder, dataExchangeSettings.ImageImportFolder); } else { ImageFolder = context.ImportFolder; } if (!System.IO.Directory.Exists(ImageDownloadFolder)) { System.IO.Directory.CreateDirectory(ImageDownloadFolder); } DownloaderContext = new FileDownloadManagerContext { Timeout = TimeSpan.FromMinutes(dataExchangeSettings.ImageDownloadTimeout), Logger = context.Log, CancellationToken = context.CancellationToken }; }
private int ProcessLocalizations(IImportExecuteContext context, ImportRow <Category>[] batch) { foreach (var row in batch) { foreach (var lang in context.Languages) { var name = row.GetDataValue <string>("Name", lang.UniqueSeoCode); var fullName = row.GetDataValue <string>("FullName", lang.UniqueSeoCode); var description = row.GetDataValue <string>("Description", lang.UniqueSeoCode); var bottomDescription = row.GetDataValue <string>("BottomDescription", lang.UniqueSeoCode); var metaKeywords = row.GetDataValue <string>("MetaKeywords", lang.UniqueSeoCode); var metaDescription = row.GetDataValue <string>("MetaDescription", lang.UniqueSeoCode); var metaTitle = row.GetDataValue <string>("MetaTitle", lang.UniqueSeoCode); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.Name, name, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.FullName, fullName, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.Description, description, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.BottomDescription, bottomDescription, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaKeywords, metaKeywords, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaDescription, metaDescription, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaTitle, metaTitle, lang.Id); } } var num = _categoryRepository.Context.SaveChanges(); return(num); }
private int ProcessParentMappings(IImportExecuteContext context, ImportRow <Category>[] batch, Dictionary <int, ImportCategoryMapping> srcToDestId) { foreach (var row in batch) { var id = row.GetDataValue <int>("Id"); var rawParentId = row.GetDataValue <string>("ParentCategoryId"); var parentId = rawParentId.ToInt(-1); if (id != 0 && parentId != -1 && srcToDestId.ContainsKey(id) && srcToDestId.ContainsKey(parentId)) { // only touch hierarchical data if child and parent were inserted if (srcToDestId[id].Inserted && srcToDestId[parentId].Inserted && srcToDestId[id].DestinationId != 0) { var category = _categoryRepository.GetById(srcToDestId[id].DestinationId); if (category != null) { category.ParentCategoryId = srcToDestId[parentId].DestinationId; _categoryRepository.Update(category); } } } } var num = _categoryRepository.Context.SaveChanges(); return(num); }
private int ProcessLocalizations(IImportExecuteContext context, ImportRow <Product>[] batch) { foreach (var row in batch) { foreach (var lang in context.Languages) { var name = row.GetDataValue <string>("Name", lang.UniqueSeoCode); var shortDescription = row.GetDataValue <string>("ShortDescription", lang.UniqueSeoCode); var fullDescription = row.GetDataValue <string>("FullDescription", lang.UniqueSeoCode); var metaKeywords = row.GetDataValue <string>("MetaKeywords", lang.UniqueSeoCode); var metaDescription = row.GetDataValue <string>("MetaDescription", lang.UniqueSeoCode); var metaTitle = row.GetDataValue <string>("MetaTitle", lang.UniqueSeoCode); var bundleTitleText = row.GetDataValue <string>("BundleTitleText", lang.UniqueSeoCode); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.Name, name, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.ShortDescription, shortDescription, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.FullDescription, fullDescription, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaKeywords, metaKeywords, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaDescription, metaDescription, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.MetaTitle, metaTitle, lang.Id); _localizedEntityService.SaveLocalizedValue(row.Entity, x => x.BundleTitleText, bundleTitleText, lang.Id); } } // commit whole batch at once var num = _productManufacturerRepository.Context.SaveChanges(); return(num); }
private int ProcessProductMappings(IImportExecuteContext context, ImportRow <Product>[] batch, Dictionary <int, ImportProductMapping> srcToDestId) { foreach (var row in batch) { var id = row.GetDataValue <int>("Id"); var parentGroupedProductId = row.GetDataValue <int>("ParentGroupedProductId"); if (id != 0 && parentGroupedProductId != 0 && srcToDestId.ContainsKey(id) && srcToDestId.ContainsKey(parentGroupedProductId)) { // only touch relationship if child and parent were inserted if (srcToDestId[id].Inserted && srcToDestId[parentGroupedProductId].Inserted && srcToDestId[id].DestinationId != 0) { var product = _productRepository.GetById(srcToDestId[id].DestinationId); if (product != null) { product.ParentGroupedProductId = srcToDestId[parentGroupedProductId].DestinationId; _productRepository.Update(product); } } } } var num = _productRepository.Context.SaveChanges(); return(num); }
private int ProcessSlugs(IImportExecuteContext context, ImportRow <Category>[] batch) { var slugMap = new Dictionary <string, UrlRecord>(100); Func <string, UrlRecord> slugLookup = ((s) => { if (slugMap.ContainsKey(s)) { return(slugMap[s]); } return((UrlRecord)null); }); var entityName = typeof(Category).Name; foreach (var row in batch) { if (row.IsNew || row.NameChanged || row.Segmenter.HasColumn("SeName")) { try { string seName = row.GetDataValue <string>("SeName"); seName = row.Entity.ValidateSeName(seName, row.Entity.Name, true, _urlRecordService, _seoSettings, extraSlugLookup: slugLookup); UrlRecord urlRecord = null; if (row.IsNew) { // dont't bother validating SeName for new entities. urlRecord = new UrlRecord { EntityId = row.Entity.Id, EntityName = entityName, Slug = seName, LanguageId = 0, IsActive = true, }; _urlRecordRepository.Insert(urlRecord); } else { urlRecord = _urlRecordService.SaveSlug(row.Entity, seName, 0); } if (urlRecord != null) { // a new record was inserted to the store: keep track of it for this batch. slugMap[seName] = urlRecord; } } catch (Exception exception) { context.Result.AddWarning(exception.Message, row.GetRowInfo(), "SeName"); } } } // commit whole batch at once return(_urlRecordRepository.Context.SaveChanges()); }
private int ProcessProductCategories(IImportExecuteContext context, ImportRow <Product>[] batch) { _productCategoryRepository.AutoCommitEnabled = false; ProductCategory lastInserted = null; foreach (var row in batch) { var categoryIds = row.GetDataValue <List <int> >("CategoryIds"); if (categoryIds != null && categoryIds.Any()) { try { foreach (var id in categoryIds) { if (_productCategoryRepository.TableUntracked.Where(x => x.ProductId == row.Entity.Id && x.CategoryId == id).FirstOrDefault() == null) { // ensure that category exists var category = _categoryService.GetCategoryById(id); if (category != null) { var productCategory = new ProductCategory { ProductId = row.Entity.Id, CategoryId = category.Id, IsFeaturedProduct = false, DisplayOrder = 1 }; _productCategoryRepository.Insert(productCategory); lastInserted = productCategory; } } } } catch (Exception exception) { context.Result.AddWarning(exception.Message, row.GetRowInfo(), "CategoryIds"); } } } // commit whole batch at once var num = _productCategoryRepository.Context.SaveChanges(); // Perf: notify only about LAST insertion and update if (lastInserted != null) { _services.EventPublisher.EntityInserted(lastInserted); } return(num); }
private void ProcessStoreMappings(IImportExecuteContext context, ImportRow <Category>[] batch) { foreach (var row in batch) { var limitedToStore = row.GetDataValue <bool>("LimitedToStores"); if (limitedToStore) { var storeIds = row.GetDataValue <List <int> >("StoreIds"); _storeMappingService.SaveStoreMappings(row.Entity, storeIds == null ? new int[0] : storeIds.ToArray()); } } }
private void ProcessGenericAttributes(IImportExecuteContext context, ImportRow <Customer>[] batch, List <int> allCountryIds, List <int> allStateProvinceIds, List <string> allCustomerNumbers) { foreach (var row in batch) { SaveAttribute(row, SystemCustomerAttributeNames.FirstName); SaveAttribute(row, SystemCustomerAttributeNames.LastName); if (_dateTimeSettings.AllowCustomersToSetTimeZone) { SaveAttribute(row, SystemCustomerAttributeNames.TimeZoneId); } if (_customerSettings.GenderEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.Gender); } if (_customerSettings.DateOfBirthEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.DateOfBirth); } if (_customerSettings.CompanyEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.Company); } if (_customerSettings.StreetAddressEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.StreetAddress); } if (_customerSettings.StreetAddress2Enabled) { SaveAttribute(row, SystemCustomerAttributeNames.StreetAddress2); } if (_customerSettings.ZipPostalCodeEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.ZipPostalCode); } if (_customerSettings.CityEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.City); } if (_customerSettings.CountryEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.CountryId); } if (_customerSettings.CountryEnabled && _customerSettings.StateProvinceEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.StateProvinceId); } if (_customerSettings.PhoneEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.Phone); } if (_customerSettings.FaxEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.Fax); } if (_forumSettings.ForumsEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.ForumPostCount); } if (_forumSettings.SignaturesEnabled) { SaveAttribute(row, SystemCustomerAttributeNames.Signature); } var countryId = row.GetDataValue <int>("CountryId"); var stateProvinceId = row.GetDataValue <int>("StateProvinceId"); if (countryId != 0 && allCountryIds.Contains(countryId)) { _genericAttributeService.SaveAttribute(row.Entity.Id, SystemCustomerAttributeNames.CountryId, _attributeKeyGroup, countryId); } if (stateProvinceId != 0 && allStateProvinceIds.Contains(stateProvinceId)) { _genericAttributeService.SaveAttribute(row.Entity.Id, SystemCustomerAttributeNames.StateProvinceId, _attributeKeyGroup, stateProvinceId); } string customerNumber = null; if (_customerSettings.CustomerNumberMethod == CustomerNumberMethod.AutomaticallySet) { customerNumber = row.Entity.Id.ToString(); } else { customerNumber = row.GetDataValue <string>("CustomerNumber"); } if (customerNumber.IsEmpty() || !allCustomerNumbers.Any(x => x.IsCaseInsensitiveEqual(customerNumber))) { _genericAttributeService.SaveAttribute(row.Entity.Id, SystemCustomerAttributeNames.CustomerNumber, _attributeKeyGroup, customerNumber); if (!customerNumber.IsEmpty()) { allCustomerNumbers.Add(customerNumber); } } if (_customerSettings.AllowCustomersToUploadAvatars) { ImportAvatar(context, row); } _services.DbContext.SaveChanges(); } }
protected override void Import(IImportExecuteContext context) { var srcToDestId = new Dictionary <int, ImportCategoryMapping>(); var templateViewPaths = _categoryTemplateService.GetAllCategoryTemplates() .GroupBy(x => x.ViewPath, StringComparer.OrdinalIgnoreCase) .ToDictionary(x => x.Key, x => x.First().Id); using (var scope = new DbContextScope(ctx: _categoryRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) { var segmenter = context.GetSegmenter <Category>(); Init(context, _dataExchangeSettings); context.Result.TotalRecords = segmenter.TotalRows; while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch()) { var batch = segmenter.CurrentBatch; // Perf: detach all entities _categoryRepository.Context.DetachAll(false); context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows); try { ProcessCategories(context, batch, templateViewPaths, srcToDestId); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessCategories"); } // reduce batch to saved (valid) products. // No need to perform import operations on errored products. batch = batch.Where(x => x.Entity != null && !x.IsTransient).ToArray(); // update result object context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient); context.Result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient); // process slugs if (segmenter.HasColumn("SeName") || batch.Any(x => x.IsNew || x.NameChanged)) { try { _categoryRepository.Context.AutoDetectChangesEnabled = true; ProcessSlugs(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessSlugs"); } finally { _categoryRepository.Context.AutoDetectChangesEnabled = false; } } // process store mappings if (segmenter.HasColumn("LimitedToStores") && segmenter.HasColumn("StoreIds")) { try { _categoryRepository.Context.AutoDetectChangesEnabled = true; ProcessStoreMappings(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessStoreMappings"); } finally { _categoryRepository.Context.AutoDetectChangesEnabled = false; } } // localizations try { ProcessLocalizations(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessLocalizedProperties"); } // process pictures if (srcToDestId.Any() && segmenter.HasColumn("ImageUrl")) { try { _categoryRepository.Context.AutoDetectChangesEnabled = true; ProcessPictures(context, batch, srcToDestId); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessPictures"); } finally { _categoryRepository.Context.AutoDetectChangesEnabled = false; } } } // map parent id of inserted categories if (srcToDestId.Any() && segmenter.HasColumn("Id") && segmenter.HasColumn("ParentCategoryId")) { segmenter.Reset(); while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch()) { var batch = segmenter.CurrentBatch; _categoryRepository.Context.DetachAll(false); try { ProcessParentMappings(context, batch, srcToDestId); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessParentMappings"); } } } } }
private int ProcessCategories(IImportExecuteContext context, ImportRow <Category>[] batch, Dictionary <string, int> templateViewPaths, Dictionary <int, ImportCategoryMapping> srcToDestId) { _categoryRepository.AutoCommitEnabled = true; Category lastInserted = null; Category lastUpdated = null; var defaultTemplateId = templateViewPaths["CategoryTemplate.ProductsInGridOrLines"]; foreach (var row in batch) { Category category = null; var id = row.GetDataValue <int>("Id"); var name = row.GetDataValue <string>("Name"); foreach (var keyName in context.KeyFieldNames) { switch (keyName) { case "Id": if (id != 0) { category = _categoryRepository.GetById(id); } break; case "Name": if (name.HasValue()) { category = _categoryRepository.Table.FirstOrDefault(x => x.Name == name); } break; } if (category != null) { break; } } if (category == null) { if (context.UpdateOnly) { ++context.Result.SkippedRecords; continue; } // a Name is required with new categories if (!row.Segmenter.HasColumn("Name")) { ++context.Result.SkippedRecords; context.Result.AddError("The 'Name' field is required for new categories. Skipping row.", row.GetRowInfo(), "Name"); continue; } category = new Category(); } row.Initialize(category, name); if (!row.IsNew && !category.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) { // Perf: use this later for SeName updates. row.NameChanged = true; } row.SetProperty(context.Result, category, (x) => x.Name); row.SetProperty(context.Result, category, (x) => x.FullName); row.SetProperty(context.Result, category, (x) => x.Description); row.SetProperty(context.Result, category, (x) => x.BottomDescription); row.SetProperty(context.Result, category, (x) => x.MetaKeywords); row.SetProperty(context.Result, category, (x) => x.MetaDescription); row.SetProperty(context.Result, category, (x) => x.MetaTitle); row.SetProperty(context.Result, category, (x) => x.PageSize, 12); row.SetProperty(context.Result, category, (x) => x.AllowCustomersToSelectPageSize, true); row.SetProperty(context.Result, category, (x) => x.PageSizeOptions); row.SetProperty(context.Result, category, (x) => x.PriceRanges); row.SetProperty(context.Result, category, (x) => x.ShowOnHomePage); row.SetProperty(context.Result, category, (x) => x.HasDiscountsApplied); row.SetProperty(context.Result, category, (x) => x.Published, true); row.SetProperty(context.Result, category, (x) => x.DisplayOrder); row.SetProperty(context.Result, category, (x) => x.LimitedToStores); row.SetProperty(context.Result, category, (x) => x.Alias); row.SetProperty(context.Result, category, (x) => x.DefaultViewMode); var tvp = row.GetDataValue <string>("CategoryTemplateViewPath"); category.CategoryTemplateId = (tvp.HasValue() && templateViewPaths.ContainsKey(tvp) ? templateViewPaths[tvp] : defaultTemplateId); row.SetProperty(context.Result, category, (x) => x.CreatedOnUtc, UtcNow); category.UpdatedOnUtc = UtcNow; if (id != 0 && !srcToDestId.ContainsKey(id)) { srcToDestId.Add(id, new ImportCategoryMapping { Inserted = row.IsTransient }); } if (row.IsTransient) { _categoryRepository.Insert(category); lastInserted = category; } else { _categoryRepository.Update(category); lastUpdated = category; } } // commit whole batch at once var num = _categoryRepository.Context.SaveChanges(); // get new category ids foreach (var row in batch) { var id = row.GetDataValue <int>("Id"); if (id != 0 && srcToDestId.ContainsKey(id)) { srcToDestId[id].DestinationId = row.Entity.Id; } } // Perf: notify only about LAST insertion and update if (lastInserted != null) { _services.EventPublisher.EntityInserted(lastInserted); } if (lastUpdated != null) { _services.EventPublisher.EntityUpdated(lastUpdated); } return(num); }
private int ProcessPictures(IImportExecuteContext context, ImportRow <Category>[] batch, Dictionary <int, ImportCategoryMapping> srcToDestId) { Picture picture = null; var equalPictureId = 0; foreach (var row in batch) { try { var srcId = row.GetDataValue <int>("Id"); var urlOrPath = row.GetDataValue <string>("ImageUrl"); if (srcId != 0 && srcToDestId.ContainsKey(srcId) && urlOrPath.HasValue()) { var currentPictures = new List <Picture>(); var category = _categoryRepository.GetById(srcToDestId[srcId].DestinationId); var seoName = _pictureService.GetPictureSeName(row.EntityDisplayName); var image = CreateDownloadImage(urlOrPath, seoName, 1); if (category != null && image != null) { if (image.Url.HasValue() && !image.Success.HasValue) { AsyncRunner.RunSync(() => _fileDownloadManager.DownloadAsync(DownloaderContext, new FileDownloadManagerItem[] { image })); } if ((image.Success ?? false) && File.Exists(image.Path)) { Succeeded(image); var pictureBinary = File.ReadAllBytes(image.Path); if (pictureBinary != null && pictureBinary.Length > 0) { if (category.PictureId.HasValue && (picture = _pictureRepository.GetById(category.PictureId.Value)) != null) { currentPictures.Add(picture); } pictureBinary = _pictureService.ValidatePicture(pictureBinary); pictureBinary = _pictureService.FindEqualPicture(pictureBinary, currentPictures, out equalPictureId); if (pictureBinary != null && pictureBinary.Length > 0) { if ((picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, false, false)) != null) { category.PictureId = picture.Id; _categoryRepository.Update(category); } } else { context.Result.AddInfo("Found equal picture in data store. Skipping field.", row.GetRowInfo(), "ImageUrls"); } } } else if (image.Url.HasValue()) { context.Result.AddInfo("Download of an image failed.", row.GetRowInfo(), "ImageUrls"); } } } } catch (Exception exception) { context.Result.AddWarning(exception.ToAllMessages(), row.GetRowInfo(), "ImageUrls"); } } var num = _categoryRepository.Context.SaveChanges(); return(num); }
private void ProcessProductPicturesOld(IImportExecuteContext context, ImportRow <Product>[] batch) { // true, cause pictures must be saved and assigned an id prior adding a mapping. _productPictureRepository.AutoCommitEnabled = true; ProductPicture lastInserted = null; var equalPictureId = 0; foreach (var row in batch) { var count = -1; var thumbPaths = row.GetDataValue <List <string> >("PictureThumbPaths"); if (thumbPaths == null) { continue; } foreach (var path in thumbPaths.Where(x => x.HasValue() && File.Exists(x))) { try { var currentProductPictures = _productPictureRepository.TableUntracked.Expand(x => x.Picture) .Where(x => x.ProductId == row.Entity.Id) .ToList(); var currentPictures = currentProductPictures .Select(x => x.Picture) .ToList(); if (count == -1) { count = (currentProductPictures.Any() ? currentProductPictures.Select(x => x.DisplayOrder).Max() : 0); } var pictureBinary = _pictureService.FindEqualPicture(path, currentPictures, out equalPictureId); if (pictureBinary != null && pictureBinary.Length > 0) { // no equal picture found in sequence var newPicture = _pictureService.InsertPicture(pictureBinary, "image/jpeg", _pictureService.GetPictureSeName(row.EntityDisplayName), true, false, false); if (newPicture != null) { var mapping = new ProductPicture { ProductId = row.Entity.Id, PictureId = newPicture.Id, DisplayOrder = ++count }; _productPictureRepository.Insert(mapping); lastInserted = mapping; } } else { var idx = thumbPaths.IndexOf(path) + 1; context.Result.AddInfo("Found equal picture in data store. Skipping field.", row.GetRowInfo(), "PictureThumbPaths" + idx.ToString()); } } catch (Exception exception) { var idx = thumbPaths.IndexOf(path) + 1; context.Result.AddWarning(exception.Message, row.GetRowInfo(), "PictureThumbPaths" + idx.ToString()); } } } // Perf: notify only about LAST insertion and update if (lastInserted != null) { _services.EventPublisher.EntityInserted(lastInserted); } }
private void ImportAvatar(IImportExecuteContext context, ImportRow <Customer> row) { var urlOrPath = row.GetDataValue <string>("AvatarPictureUrl"); if (urlOrPath.IsEmpty()) { return; } Picture picture = null; var equalPictureId = 0; var currentPictures = new List <Picture>(); var seoName = _pictureService.GetPictureSeName(row.EntityDisplayName); var image = CreateDownloadImage(urlOrPath, seoName, 1); if (image == null) { return; } if (image.Url.HasValue() && !image.Success.HasValue) { AsyncRunner.RunSync(() => _fileDownloadManager.DownloadAsync(DownloaderContext, new FileDownloadManagerItem[] { image })); } if ((image.Success ?? false) && File.Exists(image.Path)) { Succeeded(image); var pictureBinary = File.ReadAllBytes(image.Path); if (pictureBinary != null && pictureBinary.Length > 0) { var currentPictureId = row.Entity.GetAttribute <int>(SystemCustomerAttributeNames.AvatarPictureId); if (currentPictureId != 0 && (picture = _pictureRepository.GetById(currentPictureId)) != null) { currentPictures.Add(picture); } pictureBinary = _pictureService.ValidatePicture(pictureBinary); pictureBinary = _pictureService.FindEqualPicture(pictureBinary, currentPictures, out equalPictureId); if (pictureBinary != null && pictureBinary.Length > 0) { if ((picture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, false, false)) != null) { _pictureRepository.Context.SaveChanges(); _genericAttributeService.SaveAttribute(row.Entity.Id, SystemCustomerAttributeNames.AvatarPictureId, _attributeKeyGroup, picture.Id.ToString()); } } else { context.Result.AddInfo("Found equal picture in data store. Skipping field.", row.GetRowInfo(), "AvatarPictureUrl"); } } } else { context.Result.AddInfo("Download of an image failed.", row.GetRowInfo(), "AvatarPictureUrl"); } }
protected override void Import(IImportExecuteContext context) { var srcToDestId = new Dictionary <int, ImportProductMapping>(); var templateViewPaths = _productTemplateService.GetAllProductTemplates() .GroupBy(x => x.ViewPath, StringComparer.OrdinalIgnoreCase) .ToDictionary(x => x.Key, x => x.First().Id); using (var scope = new DbContextScope(ctx: _productRepository.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false)) { var segmenter = context.GetSegmenter <Product>(); Init(context, _dataExchangeSettings); context.Result.TotalRecords = segmenter.TotalRows; while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch()) { var batch = segmenter.CurrentBatch; // Perf: detach all entities _productRepository.Context.DetachAll(false); context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows); // =========================================================================== // 1.) Import products // =========================================================================== try { ProcessProducts(context, batch, templateViewPaths, srcToDestId); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProducts"); } // reduce batch to saved (valid) products. // No need to perform import operations on errored products. batch = batch.Where(x => x.Entity != null && !x.IsTransient).ToArray(); // update result object context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient); context.Result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient); // =========================================================================== // 2.) Import SEO Slugs // IMPORTANT: Unlike with Products AutoCommitEnabled must be TRUE, // as Slugs are going to be validated against existing ones in DB. // =========================================================================== if (segmenter.HasColumn("SeName") || batch.Any(x => x.IsNew || x.NameChanged)) { try { _productRepository.Context.AutoDetectChangesEnabled = true; ProcessSlugs(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessSlugs"); } finally { _productRepository.Context.AutoDetectChangesEnabled = false; } } if (segmenter.HasColumn("LimitedToStores") && segmenter.HasColumn("StoreIds")) { try { _productRepository.Context.AutoDetectChangesEnabled = true; ProcessStoreMappings(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessStoreMappings"); } finally { _productRepository.Context.AutoDetectChangesEnabled = false; } } // =========================================================================== // 3.) Import Localizations // =========================================================================== try { ProcessLocalizations(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessLocalizations"); } // =========================================================================== // 4.) Import product category mappings // =========================================================================== if (segmenter.HasColumn("CategoryIds")) { try { ProcessProductCategories(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductCategories"); } } // =========================================================================== // 5.) Import product manufacturer mappings // =========================================================================== if (segmenter.HasColumn("ManufacturerIds")) { try { ProcessProductManufacturers(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductManufacturers"); } } // =========================================================================== // 6.) Import product picture mappings // =========================================================================== if (segmenter.HasColumn("ImageUrls")) { try { ProcessProductPictures(context, batch); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessProductPictures"); } } } // =========================================================================== // 7.) Map parent id of inserted products // =========================================================================== if (srcToDestId.Any() && segmenter.HasColumn("Id") && segmenter.HasColumn("ParentGroupedProductId")) { segmenter.Reset(); while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch()) { var batch = segmenter.CurrentBatch; _productRepository.Context.DetachAll(false); try { ProcessProductMappings(context, batch, srcToDestId); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessParentMappings"); } } } } }
private int ProcessProducts( IImportExecuteContext context, ImportRow <Product>[] batch, Dictionary <string, int> templateViewPaths, Dictionary <int, ImportProductMapping> srcToDestId) { _productRepository.AutoCommitEnabled = true; Product lastInserted = null; Product lastUpdated = null; var defaultTemplateId = templateViewPaths["ProductTemplate.Simple"]; foreach (var row in batch) { Product product = null; var id = row.GetDataValue <int>("Id"); foreach (var keyName in context.KeyFieldNames) { switch (keyName) { case "Id": product = _productService.GetProductById(id); break; case "Sku": product = _productService.GetProductBySku(row.GetDataValue <string>("Sku")); break; case "Gtin": product = _productService.GetProductByGtin(row.GetDataValue <string>("Gtin")); break; case "ManufacturerPartNumber": product = _productService.GetProductByManufacturerPartNumber(row.GetDataValue <string>("ManufacturerPartNumber")); break; case "Name": product = _productService.GetProductByName(row.GetDataValue <string>("Name")); break; } if (product != null) { break; } } if (product == null) { if (context.UpdateOnly) { ++context.Result.SkippedRecords; continue; } // a Name is required with new products. if (!row.Segmenter.HasColumn("Name")) { ++context.Result.SkippedRecords; context.Result.AddError("The 'Name' field is required for new products. Skipping row.", row.GetRowInfo(), "Name"); continue; } product = new Product(); } var name = row.GetDataValue <string>("Name"); row.Initialize(product, name); if (!row.IsNew) { if (!product.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) { // Perf: use this later for SeName updates. row.NameChanged = true; } } row.SetProperty(context.Result, product, (x) => x.ProductTypeId, (int)ProductType.SimpleProduct); row.SetProperty(context.Result, product, (x) => x.VisibleIndividually, true); row.SetProperty(context.Result, product, (x) => x.Name); row.SetProperty(context.Result, product, (x) => x.ShortDescription); row.SetProperty(context.Result, product, (x) => x.FullDescription); row.SetProperty(context.Result, product, (x) => x.AdminComment); row.SetProperty(context.Result, product, (x) => x.ShowOnHomePage); row.SetProperty(context.Result, product, (x) => x.HomePageDisplayOrder); row.SetProperty(context.Result, product, (x) => x.MetaKeywords); row.SetProperty(context.Result, product, (x) => x.MetaDescription); row.SetProperty(context.Result, product, (x) => x.MetaTitle); row.SetProperty(context.Result, product, (x) => x.AllowCustomerReviews, true); row.SetProperty(context.Result, product, (x) => x.ApprovedRatingSum); row.SetProperty(context.Result, product, (x) => x.NotApprovedRatingSum); row.SetProperty(context.Result, product, (x) => x.ApprovedTotalReviews); row.SetProperty(context.Result, product, (x) => x.NotApprovedTotalReviews); row.SetProperty(context.Result, product, (x) => x.Published, true); row.SetProperty(context.Result, product, (x) => x.Sku); row.SetProperty(context.Result, product, (x) => x.ManufacturerPartNumber); row.SetProperty(context.Result, product, (x) => x.Gtin); row.SetProperty(context.Result, product, (x) => x.IsGiftCard); row.SetProperty(context.Result, product, (x) => x.GiftCardTypeId); row.SetProperty(context.Result, product, (x) => x.RequireOtherProducts); row.SetProperty(context.Result, product, (x) => x.RequiredProductIds); // TODO: global scope row.SetProperty(context.Result, product, (x) => x.AutomaticallyAddRequiredProducts); row.SetProperty(context.Result, product, (x) => x.IsDownload); row.SetProperty(context.Result, product, (x) => x.DownloadId); row.SetProperty(context.Result, product, (x) => x.UnlimitedDownloads, true); row.SetProperty(context.Result, product, (x) => x.MaxNumberOfDownloads, 10); row.SetProperty(context.Result, product, (x) => x.DownloadExpirationDays); row.SetProperty(context.Result, product, (x) => x.DownloadActivationTypeId, 1); row.SetProperty(context.Result, product, (x) => x.HasSampleDownload); row.SetProperty(context.Result, product, (x) => x.SampleDownloadId, (int?)null, ZeroToNull); // TODO: global scope row.SetProperty(context.Result, product, (x) => x.HasUserAgreement); row.SetProperty(context.Result, product, (x) => x.UserAgreementText); row.SetProperty(context.Result, product, (x) => x.IsRecurring); row.SetProperty(context.Result, product, (x) => x.RecurringCycleLength, 100); row.SetProperty(context.Result, product, (x) => x.RecurringCyclePeriodId); row.SetProperty(context.Result, product, (x) => x.RecurringTotalCycles, 10); row.SetProperty(context.Result, product, (x) => x.IsShipEnabled, true); row.SetProperty(context.Result, product, (x) => x.IsFreeShipping); row.SetProperty(context.Result, product, (x) => x.AdditionalShippingCharge); row.SetProperty(context.Result, product, (x) => x.IsEsd); row.SetProperty(context.Result, product, (x) => x.IsTaxExempt); row.SetProperty(context.Result, product, (x) => x.TaxCategoryId, 1); // TODO: global scope row.SetProperty(context.Result, product, (x) => x.ManageInventoryMethodId); row.SetProperty(context.Result, product, (x) => x.StockQuantity, 10000); row.SetProperty(context.Result, product, (x) => x.DisplayStockAvailability); row.SetProperty(context.Result, product, (x) => x.DisplayStockQuantity); row.SetProperty(context.Result, product, (x) => x.MinStockQuantity); row.SetProperty(context.Result, product, (x) => x.LowStockActivityId); row.SetProperty(context.Result, product, (x) => x.NotifyAdminForQuantityBelow, 1); row.SetProperty(context.Result, product, (x) => x.BackorderModeId); row.SetProperty(context.Result, product, (x) => x.AllowBackInStockSubscriptions); row.SetProperty(context.Result, product, (x) => x.OrderMinimumQuantity, 1); row.SetProperty(context.Result, product, (x) => x.OrderMaximumQuantity, 10000); row.SetProperty(context.Result, product, (x) => x.AllowedQuantities); row.SetProperty(context.Result, product, (x) => x.DisableBuyButton); row.SetProperty(context.Result, product, (x) => x.DisableWishlistButton); row.SetProperty(context.Result, product, (x) => x.AvailableForPreOrder); row.SetProperty(context.Result, product, (x) => x.CallForPrice); row.SetProperty(context.Result, product, (x) => x.Price); row.SetProperty(context.Result, product, (x) => x.OldPrice); row.SetProperty(context.Result, product, (x) => x.ProductCost); row.SetProperty(context.Result, product, (x) => x.SpecialPrice); row.SetProperty(context.Result, product, (x) => x.SpecialPriceStartDateTimeUtc); row.SetProperty(context.Result, product, (x) => x.SpecialPriceEndDateTimeUtc); row.SetProperty(context.Result, product, (x) => x.CustomerEntersPrice); row.SetProperty(context.Result, product, (x) => x.MinimumCustomerEnteredPrice); row.SetProperty(context.Result, product, (x) => x.MaximumCustomerEnteredPrice, 1000); // HasTierPrices... ignore as long as no tier prices are imported // LowestAttributeCombinationPrice... ignore as long as no combinations are imported row.SetProperty(context.Result, product, (x) => x.Weight); row.SetProperty(context.Result, product, (x) => x.Length); row.SetProperty(context.Result, product, (x) => x.Width); row.SetProperty(context.Result, product, (x) => x.Height); row.SetProperty(context.Result, product, (x) => x.DisplayOrder); row.SetProperty(context.Result, product, (x) => x.DeliveryTimeId); // TODO: global scope row.SetProperty(context.Result, product, (x) => x.QuantityUnitId); // TODO: global scope row.SetProperty(context.Result, product, (x) => x.BasePriceEnabled); row.SetProperty(context.Result, product, (x) => x.BasePriceMeasureUnit); row.SetProperty(context.Result, product, (x) => x.BasePriceAmount); row.SetProperty(context.Result, product, (x) => x.BasePriceBaseAmount); row.SetProperty(context.Result, product, (x) => x.BundleTitleText); row.SetProperty(context.Result, product, (x) => x.BundlePerItemShipping); row.SetProperty(context.Result, product, (x) => x.BundlePerItemPricing); row.SetProperty(context.Result, product, (x) => x.BundlePerItemShoppingCart); row.SetProperty(context.Result, product, (x) => x.AvailableStartDateTimeUtc); row.SetProperty(context.Result, product, (x) => x.AvailableEndDateTimeUtc); row.SetProperty(context.Result, product, (x) => x.LimitedToStores); var tvp = row.GetDataValue <string>("ProductTemplateViewPath"); product.ProductTemplateId = (tvp.HasValue() && templateViewPaths.ContainsKey(tvp) ? templateViewPaths[tvp] : defaultTemplateId); row.SetProperty(context.Result, product, (x) => x.CreatedOnUtc, UtcNow); product.UpdatedOnUtc = UtcNow; if (id != 0 && !srcToDestId.ContainsKey(id)) { srcToDestId.Add(id, new ImportProductMapping { Inserted = row.IsTransient }); } if (row.IsTransient) { _productRepository.Insert(product); lastInserted = product; } else { _productRepository.Update(product); lastUpdated = product; } } // commit whole batch at once var num = _productRepository.Context.SaveChanges(); // get new product ids foreach (var row in batch) { var id = row.GetDataValue <int>("Id"); if (id != 0 && srcToDestId.ContainsKey(id)) { srcToDestId[id].DestinationId = row.Entity.Id; } } // Perf: notify only about LAST insertion and update if (lastInserted != null) { _services.EventPublisher.EntityInserted(lastInserted); } if (lastUpdated != null) { _services.EventPublisher.EntityUpdated(lastUpdated); } return(num); }
private int ProcessCustomers(IImportExecuteContext context, ImportRow <Customer>[] batch, List <int> allAffiliateIds, IList <CustomerRole> allCustomerRoles) { _customerRepository.AutoCommitEnabled = true; Customer lastInserted = null; Customer lastUpdated = null; var guestRole = allCustomerRoles.FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.Guests); var registeredRole = allCustomerRoles.FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.Registered); var adminRole = allCustomerRoles.FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.Administrators); var forumModeratorRole = allCustomerRoles.FirstOrDefault(x => x.SystemName == SystemCustomerRoleNames.ForumModerators); foreach (var row in batch) { Customer customer = null; var id = row.GetDataValue <int>("Id"); var email = row.GetDataValue <string>("Email"); foreach (var keyName in context.KeyFieldNames) { switch (keyName) { case "Id": customer = _customerService.GetCustomerById(id); break; case "CustomerGuid": var guid = row.GetDataValue <string>("CustomerGuid"); if (guid.HasValue()) { customer = _customerService.GetCustomerByGuid(new Guid(guid)); } break; case "Email": customer = _customerService.GetCustomerByEmail(email); break; case "Username": customer = _customerService.GetCustomerByUsername(row.GetDataValue <string>("Username")); break; } if (customer != null) { break; } } if (customer == null) { if (context.UpdateOnly) { ++context.Result.SkippedRecords; continue; } customer = new Customer { CustomerGuid = new Guid(), AffiliateId = 0, Active = true }; } else { _customerRepository.Context.LoadCollection(customer, (Customer x) => x.CustomerRoles); } var isGuest = row.GetDataValue <bool>("IsGuest"); var isRegistered = row.GetDataValue <bool>("IsRegistered"); var isAdmin = row.GetDataValue <bool>("IsAdministrator"); var isForumModerator = row.GetDataValue <bool>("IsForumModerator"); var affiliateId = row.GetDataValue <int>("AffiliateId"); row.Initialize(customer, email.HasValue() ? email : id.ToString()); row.SetProperty(context.Result, customer, (x) => x.CustomerGuid); row.SetProperty(context.Result, customer, (x) => x.Username); row.SetProperty(context.Result, customer, (x) => x.Email); row.SetProperty(context.Result, customer, (x) => x.Password); row.SetProperty(context.Result, customer, (x) => x.PasswordFormatId); row.SetProperty(context.Result, customer, (x) => x.PasswordSalt); row.SetProperty(context.Result, customer, (x) => x.AdminComment); row.SetProperty(context.Result, customer, (x) => x.IsTaxExempt); row.SetProperty(context.Result, customer, (x) => x.Active); row.SetProperty(context.Result, customer, (x) => x.IsSystemAccount); row.SetProperty(context.Result, customer, (x) => x.SystemName); row.SetProperty(context.Result, customer, (x) => x.LastIpAddress); row.SetProperty(context.Result, customer, (x) => x.LastLoginDateUtc); row.SetProperty(context.Result, customer, (x) => x.LastActivityDateUtc); row.SetProperty(context.Result, customer, (x) => x.CreatedOnUtc, UtcNow); row.SetProperty(context.Result, customer, (x) => x.LastActivityDateUtc, UtcNow); if (affiliateId > 0 && allAffiliateIds.Contains(affiliateId)) { customer.AffiliateId = affiliateId; } UpsertRole(row, guestRole, SystemCustomerRoleNames.Guests, isGuest); UpsertRole(row, registeredRole, SystemCustomerRoleNames.Registered, isRegistered); UpsertRole(row, adminRole, SystemCustomerRoleNames.Administrators, isAdmin); UpsertRole(row, forumModeratorRole, SystemCustomerRoleNames.ForumModerators, isForumModerator); if (row.IsTransient) { _customerRepository.Insert(customer); lastInserted = customer; } else { _customerRepository.Update(customer); lastUpdated = customer; } } var num = _customerRepository.Context.SaveChanges(); if (lastInserted != null) { _services.EventPublisher.EntityInserted(lastInserted); } if (lastUpdated != null) { _services.EventPublisher.EntityUpdated(lastUpdated); } return(num); }
public void Execute(IImportExecuteContext context) { Import(context); }
protected override void Import(IImportExecuteContext context) { var customer = _services.WorkContext.CurrentCustomer; var allowManagingCustomerRoles = _services.Permissions.Authorize(StandardPermissionProvider.ManageCustomerRoles, customer); var allCustomerRoles = _customerService.GetAllCustomerRoles(true); var allAffiliateIds = _affiliateService.GetAllAffiliates(true) .Select(x => x.Id) .ToList(); var allCountryIds = _countryService.GetAllCountries(true) .Select(x => x.Id) .ToList(); var allStateProvinceIds = _stateProvinceService.GetAllStateProvinces(true) .Select(x => x.Id) .ToList(); var allCustomerNumbers = _genericAttributeService.GetAttributes(SystemCustomerAttributeNames.CustomerNumber, _attributeKeyGroup) .Select(x => x.Value) .ToList(); using (var scope = new DbContextScope(ctx: _services.DbContext, autoDetectChanges: false, proxyCreation: false, validateOnSave: false, autoCommit: false)) { var segmenter = context.GetSegmenter <Customer>(); Init(context, _dataExchangeSettings); context.Result.TotalRecords = segmenter.TotalRows; while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch()) { var batch = segmenter.CurrentBatch; _customerRepository.Context.DetachAll(false); context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows); try { ProcessCustomers(context, batch, allAffiliateIds, allCustomerRoles); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessCustomers"); } // reduce batch to saved (valid) records. // No need to perform import operations on errored records. batch = batch.Where(x => x.Entity != null && !x.IsTransient).ToArray(); // update result object context.Result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient); context.Result.ModifiedRecords += batch.Count(x => !x.IsNew && !x.IsTransient); try { _services.DbContext.AutoDetectChangesEnabled = true; ProcessGenericAttributes(context, batch, allCountryIds, allStateProvinceIds, allCustomerNumbers); } catch (Exception exception) { context.Result.AddError(exception, segmenter.CurrentSegment, "ProcessGenericAttributes"); } finally { _services.DbContext.AutoDetectChangesEnabled = false; } } } }
private void ProcessProductPictures(IImportExecuteContext context, ImportRow <Product>[] batch) { // true, cause pictures must be saved and assigned an id prior adding a mapping. _productPictureRepository.AutoCommitEnabled = true; ProductPicture lastInserted = null; var equalPictureId = 0; foreach (var row in batch) { var imageUrls = row.GetDataValue <List <string> >("ImageUrls"); if (imageUrls == null || !imageUrls.Any()) { continue; } var imageNumber = 0; var displayOrder = -1; var seoName = _pictureService.GetPictureSeName(row.EntityDisplayName); var imageFiles = new List <FileDownloadManagerItem>(); // collect required image file infos foreach (var urlOrPath in imageUrls) { var image = CreateDownloadImage(urlOrPath, seoName, ++imageNumber); if (image != null) { imageFiles.Add(image); } } // download images if (imageFiles.Any(x => x.Url.HasValue())) { // async downloading in batch processing is inefficient cause only the image processing benefits from async, // not the record processing itself. a per record processing may speed up the import. AsyncRunner.RunSync(() => _fileDownloadManager.DownloadAsync(DownloaderContext, imageFiles.Where(x => x.Url.HasValue() && !x.Success.HasValue))); } // import images foreach (var image in imageFiles.OrderBy(x => x.DisplayOrder)) { try { if ((image.Success ?? false) && File.Exists(image.Path)) { Succeeded(image); var pictureBinary = File.ReadAllBytes(image.Path); if (pictureBinary != null && pictureBinary.Length > 0) { var currentProductPictures = _productPictureRepository.TableUntracked.Expand(x => x.Picture) .Where(x => x.ProductId == row.Entity.Id) .ToList(); var currentPictures = currentProductPictures .Select(x => x.Picture) .ToList(); if (displayOrder == -1) { displayOrder = (currentProductPictures.Any() ? currentProductPictures.Select(x => x.DisplayOrder).Max() : 0); } pictureBinary = _pictureService.ValidatePicture(pictureBinary); pictureBinary = _pictureService.FindEqualPicture(pictureBinary, currentPictures, out equalPictureId); if (pictureBinary != null && pictureBinary.Length > 0) { // no equal picture found in sequence var newPicture = _pictureService.InsertPicture(pictureBinary, image.MimeType, seoName, true, false, false); if (newPicture != null) { var mapping = new ProductPicture { ProductId = row.Entity.Id, PictureId = newPicture.Id, DisplayOrder = ++displayOrder }; _productPictureRepository.Insert(mapping); lastInserted = mapping; } } else { context.Result.AddInfo("Found equal picture in data store. Skipping field.", row.GetRowInfo(), "ImageUrls" + image.DisplayOrder.ToString()); } } } else if (image.Url.HasValue()) { context.Result.AddInfo("Download of an image failed.", row.GetRowInfo(), "ImageUrls" + image.DisplayOrder.ToString()); } } catch (Exception exception) { context.Result.AddWarning(exception.ToAllMessages(), row.GetRowInfo(), "ImageUrls" + image.DisplayOrder.ToString()); } } } // Perf: notify only about LAST insertion and update if (lastInserted != null) { _services.EventPublisher.EntityInserted(lastInserted); } }
public void Execute(IImportExecuteContext context) { var utcNow = DateTime.UtcNow; var currentStoreId = _services.StoreContext.CurrentStore.Id; var toAdd = new List <NewsLetterSubscription>(); var toUpdate = new List <NewsLetterSubscription>(); using (var scope = new DbContextScope(ctx: _services.DbContext, autoDetectChanges: false, proxyCreation: false, validateOnSave: false, autoCommit: false)) { var segmenter = context.GetSegmenter <NewsLetterSubscription>(); context.Result.TotalRecords = segmenter.TotalRows; while (context.Abort == DataExchangeAbortion.None && segmenter.ReadNextBatch()) { var batch = segmenter.CurrentBatch; _subscriptionRepository.Context.DetachAll(false); context.SetProgress(segmenter.CurrentSegmentFirstRowIndex - 1, segmenter.TotalRows); foreach (var row in batch) { try { var email = row.GetDataValue <string>("Email"); var active = row.GetDataValue <bool>("Active"); var storeId = row.GetDataValue <int>("StoreId"); if (storeId == 0) { storeId = currentStoreId; } if (email.IsEmpty()) { context.Result.AddWarning("Skipped empty email address", row.GetRowInfo(), "Email"); continue; } if (email.Length > 255) { context.Result.AddWarning("Skipped email address '{0}'. It exceeds the maximum allowed length of 255".FormatInvariant(email), row.GetRowInfo(), "Email"); continue; } if (!email.IsEmail()) { context.Result.AddWarning("Skipped invalid email address '{0}'".FormatInvariant(email), row.GetRowInfo(), "Email"); continue; } NewsLetterSubscription subscription = null; foreach (var keyName in context.KeyFieldNames) { switch (keyName) { case "Email": subscription = _subscriptionRepository.Table .OrderBy(x => x.Id) .FirstOrDefault(x => x.Email == email && x.StoreId == storeId); break; } if (subscription != null) { break; } } if (subscription == null) { if (context.UpdateOnly) { ++context.Result.SkippedRecords; continue; } subscription = new NewsLetterSubscription { Active = active, CreatedOnUtc = utcNow, Email = email, NewsLetterSubscriptionGuid = Guid.NewGuid(), StoreId = storeId }; toAdd.Add(subscription); ++context.Result.NewRecords; } else { subscription.Active = active; toUpdate.Add(subscription); ++context.Result.ModifiedRecords; } // insert new subscribers _subscriptionRepository.AutoCommitEnabled = true; _subscriptionRepository.InsertRange(toAdd, 500); toAdd.Clear(); // update modified subscribers _subscriptionRepository.UpdateRange(toUpdate); toUpdate.Clear(); } catch (Exception exception) { context.Result.AddError(exception.ToAllMessages(), row.GetRowInfo()); } } } } }
protected abstract void Import(IImportExecuteContext context);