예제 #1
0
        /// <summary>
        /// Import products from XLSX file
        /// </summary>
        /// <param name="stream">Stream</param>
        public virtual ImportResult ImportProductsFromExcel(
			Stream stream,
			CancellationToken cancellationToken,
			IProgress<ImportProgressInfo> progress = null)
        {
            Guard.ArgumentNotNull(() => stream);

            var result = new ImportResult();
            int saved = 0;

            if (progress != null)
                progress.Report(new ImportProgressInfo { ElapsedTime = TimeSpan.Zero });

            using (var scope = new DbContextScope(ctx: _rsProduct.Context, autoDetectChanges: false, proxyCreation: false, validateOnSave: false))
            {
                try {
                    using (var segmenter = new DataSegmenter<Product>(stream))
                    {
                        result.TotalRecords = segmenter.TotalRows;

                        while (segmenter.ReadNextBatch() && !cancellationToken.IsCancellationRequested)
                        {
                            var batch = segmenter.CurrentBatch;

                            // Perf: detach all entities
                            _rsProduct.Context.DetachAll(false);

                            // Update progress for calling thread
                            if (progress != null)
                            {
                                progress.Report(new ImportProgressInfo
                                {
                                    TotalRecords = result.TotalRecords,
                                    TotalProcessed = segmenter.CurrentSegmentFirstRowIndex - 1,
                                    NewRecords = result.NewRecords,
                                    ModifiedRecords = result.ModifiedRecords,
                                    ElapsedTime = DateTime.UtcNow - result.StartDateUtc,
                                    TotalWarnings = result.Messages.Count(x => x.MessageType == ImportMessageType.Warning),
                                    TotalErrors = result.Messages.Count(x => x.MessageType == ImportMessageType.Error),
                                });
                            }

                            // ===========================================================================
                            // 1.) Import products
                            // ===========================================================================
                            try
                            {
                                saved = ProcessProducts(batch, result);
                            }
                            catch (Exception ex)
                            {
                                result.AddError(ex, 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).AsReadOnly();

                            // update result object
                            result.NewRecords += batch.Count(x => x.IsNew && !x.IsTransient);
                            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 (batch.Any(x => x.IsNew || (x.ContainsKey("SeName") || x.NameChanged)))
                            {
                                try
                                {
                                    _rsProduct.Context.AutoDetectChangesEnabled = true;
                                    ProcessSlugs(batch, result);
                                }
                                catch (Exception ex)
                                {
                                    result.AddError(ex, segmenter.CurrentSegment, "ProcessSeoSlugs");
                                }
                                finally
                                {
                                    _rsProduct.Context.AutoDetectChangesEnabled = false;
                                }
                            }

                            // ===========================================================================
                            // 3.) Import Localizations
                            // ===========================================================================
                            try
                            {
                                ProcessLocalizations(batch, result);
                            }
                            catch (Exception ex)
                            {
                                result.AddError(ex, segmenter.CurrentSegment, "ProcessLocalizations");
                            }

                            // ===========================================================================
                            // 4.) Import product category mappings
                            // ===========================================================================
                            if (batch.Any(x => x.ContainsKey("CategoryIds")))
                            {
                                try
                                {
                                    ProcessProductCategories(batch, result);
                                }
                                catch (Exception ex)
                                {
                                    result.AddError(ex, segmenter.CurrentSegment, "ProcessProductCategories");
                                }
                            }

                            // ===========================================================================
                            // 5.) Import product manufacturer mappings
                            // ===========================================================================
                            if (batch.Any(x => x.ContainsKey("ManufacturerIds")))
                            {
                                try
                                {
                                    ProcessProductManufacturers(batch, result);
                                }
                                catch (Exception ex)
                                {
                                    result.AddError(ex, segmenter.CurrentSegment, "ProcessProductManufacturers");
                                }
                            }

                            // ===========================================================================
                            // 6.) Import product picture mappings
                            // ===========================================================================
                            if (batch.Any(x => x.ContainsKey("Picture1") || x.ContainsKey("Picture2") || x.ContainsKey("Picture3")))
                            {
                                try
                                {
                                    ProcessProductPictures(batch, result);
                                }
                                catch (Exception ex)
                                {
                                    result.AddError(ex, segmenter.CurrentSegment, "ProcessProductPictures");
                                }
                            }

                        }
                    }
                }
                catch (Exception ex)
                {
                    result.AddError(ex, null, "ReadFile");
                }
            }

            result.EndDateUtc = DateTime.UtcNow;

            if (cancellationToken.IsCancellationRequested)
            {
                result.Cancelled = true;
                result.AddInfo("Import task was cancelled by user");
            }

            return result;
        }
 public void Setup()
 {
     dataSegmenter = new DataSegmenter();
 }