public Task <ImportBatchResult> RunAsync(ImportBatch batch, CancellationToken cancellationToken)
        {
            if (batch == null)
            {
                throw new ArgumentNullException(nameof(batch));
            }

            var profile = _importProfileStorage.GetImportProfile(batch.ImportProfileName);

            if (profile == null)
            {
                throw new Exception($"Import profile '{batch.ImportProfileName}' does not exist.");
            }

            var importType = _importTypeStorage.GetImportType(profile.ImportTypeName);

            var worker = _importWorkerFactory.Create(importType.WorkerType);

            var context = new ImportWorkerContext
            {
                Batch      = batch,
                ImportType = importType,
                Profile    = profile
            };

            return(worker.RunAsync(context, cancellationToken));
        }
        public async Task <ImportBatchResult> RunAsync(
            ImportWorkerContext context,
            CancellationToken cancellationToken)
        {
            Context = context ?? throw new ArgumentNullException(nameof(context));

            var result = new ImportBatchResult();

            using (var stream = File.OpenRead(context.Batch.FileName))
            {
                using (var streamReader = new StreamReader(stream, Encoding.UTF8, true, 128))
                {
                    bool   skipFirstRow = context.Profile.IsFirstRowHeading;
                    int    rowIndex     = -1;
                    string line;
                    while ((line = streamReader.ReadLine()) != null)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            //throw or skip??
                        }

                        rowIndex += 1;

                        if (skipFirstRow)
                        {
                            skipFirstRow = false;
                            continue;
                        }

                        var columns = ParseLine(line, context.Profile);
                        var row     = MapColumns(columns, context.Profile);

                        var validationResult = await ValidateRowAsync(row, rowIndex);

                        if (validationResult != null)
                        {
                            result.Failures.Add(validationResult);
                            //todo log
                            continue;
                        }

                        await OnImportRowAsync(row, rowIndex);
                    }
                }
            }

            return(result);
        }