/// <summary> /// Bulk Insert Entities in DB /// </summary> /// <typeparam name="DB">DB Context Type</typeparam> /// <typeparam name="T">Entity Type</typeparam> /// <param name="dbContext">DB Context</param> /// <param name="entities">List of Entities</param> /// <param name="identificator"> /// Expression which generate unique value for each entity. It can be one column or combination /// of columns /// </param> /// <param name="configAction">Configure Bulk Insert Options</param> /// <returns></returns> public static async Task <int> BulkInsertAsync <DB, T>(this DB dbContext, IEnumerable <T> entities, Expression <Func <T, object> > identificator, Action <BulkInsertOptions <T> > configAction = null) where DB : DbContext where T : class { var enumerable = entities.ToList(); if (!enumerable.Any()) { return(0); } var options = new BulkInsertOptions <T>(); configAction?.Invoke(options); if (options.FireTriggers) { TriggersBulk <T, DB> .RaiseInserting(enumerable, dbContext); } var config = new MapperConfiguration(conf => { conf.CreateMap <T, T>().MaxDepth(1).ForAllMembers(c => { if ((c.DestinationMember as PropertyInfo)?.PropertyType.CustomAttributes.Any(x => x.AttributeType == typeof(NotMappedAttribute)) ?? false) { c.Ignore(); } if ((c.DestinationMember as PropertyInfo)?.PropertyType.CustomAttributes.Any(x => x.AttributeType == typeof(ComplexTypeAttribute)) ?? false) { return; } if ((c.DestinationMember as PropertyInfo)?.PropertyType.IsSimple() ?? false) { return; } c.Ignore(); }); }); var mapper = config.CreateMapper(); var distEnts = enumerable.Distinct(new GenericCompare <T>(identificator)).ToList(); var ent = mapper.Map <List <T> >(distEnts); var bulkInsert = new BulkOperations().Setup <T>() .ForCollection(ent) .WithTable(string.IsNullOrEmpty(options.TableName) ? dbContext.GetTableName <T>() : options.TableName) .WithBulkCopySettings(new BulkCopySettings() { BatchSize = options.BatchSize, BulkCopyTimeout = options.Timeout, SqlBulkCopyOptions = options.SqlBulkCopyOptions }) .AddAllColumns() .DetectColumnWithCustomColumnName() .RemoveNotMappedColumns() .BulkInsert(); if (options.IdentityColumn != null) { bulkInsert = bulkInsert.SetIdentityColumn(options.IdentityColumn, ColumnDirectionType.Input); } var num = await bulkInsert.CommitAsync(dbContext.Database.Connection as SqlConnection); if (options.FireTriggers) { TriggersBulk <T, DB> .RaiseInserted(enumerable, dbContext, identificator); } return(num); }