private async Task MapIntoEntity <TEntity>(Dictionary <string, string> matchingData, string idPropertyName, UpdatePropertyOverrider <TEntity> overridingMapper, TEntity entityToUpdate, Dictionary <string, string> excelRow, bool isAutoIncrementingId, RecordMode recordMode) where TEntity : class { if (overridingMapper != null) { await overridingMapper.UpdateProperties(entityToUpdate, matchingData, excelRow, recordMode); } else { UpdateProperties(entityToUpdate, matchingData, excelRow, idPropertyName, isAutoIncrementingId); } }
/// <summary> /// /// </summary> /// <typeparam name="TEntity">The type of EF Entity</typeparam> /// <typeparam name="TId">Type of the item to use for finding</typeparam> /// <param name="matchingData">Specification for how to match spreadsheet to entity</param> /// <param name="finder">A func to look for an existing copy of the entity id. default will use "find". Runs against the DB via EF.</param> /// <param name="idPropertyName">The unique identifier property. Leave blank unless you are using an overrider to use something other than the real key.</param> /// <param name="overridingMapper">A custom mapper for mapping between excel columns and an entity. </param> /// <param name="saveBehavior">Optional configuration to change the save behavior. See ImportSaveBehavior</param> /// <param name="validator">Optional method to run custom validation on the modified entity before saving</param> /// <param name="fileLocation">Directory of source xlsx file. Defaults to temp dir</param> /// <returns></returns> public async Task <ImportResult> ImportColumnData <TEntity, TId>(DataMatchesForImport matchingData, Func <TId, Expression <Func <TEntity, bool> > > finder = null, string idPropertyName = null, UpdatePropertyOverrider <TEntity> overridingMapper = null, ImportSaveBehavior saveBehavior = null, IEntityValidator <TEntity> validator = null, string fileLocation = null) where TEntity : class, new() { if (saveBehavior == null) { saveBehavior = new ImportSaveBehavior(); } var selctedDict = BuildDictionaryFromSelected(matchingData.Selected); var keyInfo = GetEntityKeys(typeof(TEntity)); EnsureImportingEntityHasSingleKey(keyInfo); var pk = keyInfo[0]; Type idType = pk.PropertyInfo.PropertyType; if (idPropertyName == null) { idPropertyName = pk.Name; } var isImportingEntityId = selctedDict.ContainsKey(idPropertyName); var isDbGeneratedId = IsIdDbGenerated(typeof(TEntity)); EnsureNoIdColumnIncludedWhenCreatingAutoIncrementEntites(saveBehavior.RecordMode, isDbGeneratedId, isImportingEntityId); var importResult = new ImportResult { RowErrorDetails = new Dictionary <string, string>() }; var excelRows = await GetExcelRows(matchingData, fileLocation); var foundErrors = false; for (var index = 0; index < excelRows.Count; index++) { var excelRow = excelRows[index]; var rowNumber = index + 2; // add 2 to reach the first data row because the first row is a header, excel row numbers start with 1 not 0 TEntity entityToUpdate = null; try { if (ExcelRowIsBlank(excelRow)) { continue; } string idValue = null; if (isImportingEntityId) { var xlsxIdColName = selctedDict[idPropertyName]; var idStringValue = excelRow[xlsxIdColName]; entityToUpdate = await GetMatchedDbObject(finder, idStringValue, idType); ValidateDbResult(entityToUpdate, saveBehavior.RecordMode, xlsxIdColName, idStringValue); } if (entityToUpdate == null) { EnsureNoEntityCreationWithIdWhenAutoIncrementIdType(idPropertyName, isDbGeneratedId, idValue); entityToUpdate = new TEntity(); await _dbContext.Set <TEntity>().AddAsync(entityToUpdate); } await MapIntoEntity(selctedDict, idPropertyName, overridingMapper, entityToUpdate, excelRow, isDbGeneratedId, saveBehavior.RecordMode); if (validator != null) { var errors = validator.GetValidationErrors(entityToUpdate); if (errors.Any()) { throw new RowInvalidException(errors); } } else { importResult.SuccessCount++; } } catch (RowParseException e) { HandleError(importResult.RowErrorDetails, rowNumber, entityToUpdate, "Error: " + e.Message); foundErrors = true; } catch (RowInvalidException e) { HandleError(importResult.RowErrorDetails, rowNumber, entityToUpdate, "Error: " + e.Message); foundErrors = true; } catch (Exception e) { HandleError(importResult.RowErrorDetails, rowNumber, entityToUpdate, "Cannot be updated - error importing"); foundErrors = true; } if (saveBehavior.CommitMode == CommitMode.AnySuccessfulOneAtATime) { await _dbContext.SaveChangesAsync(); } } if ((saveBehavior.CommitMode == CommitMode.AnySuccessfulAtEndAsBulk) || (saveBehavior.CommitMode == CommitMode.CommitAllAtEndIfAllGoodOrRejectAll && !foundErrors)) { await _dbContext.SaveChangesAsync(); } return(importResult); }