Install "EFCore.BulkExtensions" on EntityFrameworkCore module.
Create a custom repository interface in your Core.Shared module:
public interface ICustomRepository : IRepository where TEntity : class, IEntity { int CountAsNoTracking(); int CountAsNoTracking(Expression> predicate); Task CountAsNoTrackingAsync(); Task CountAsNoTrackingAsync(Expression> predicate); TEntity FirstOrDefaultAsNoTracking(TPrimaryKey id); TEntity FirstOrDefaultAsNoTracking(Expression> predicate); Task FirstOrDefaultAsNoTrackingAsync(TPrimaryKey id); Task FirstOrDefaultAsNoTrackingAsync(Expression> predicate); IQueryable GetAllAsNoTracking(); IQueryable GetAllIncludingAsNoTracking(params Expression>[] propertySelectors); List GetAllListAsNoTracking(); List GetAllListAsNoTracking(Expression> predicate); Task> GetAllListAsNoTrackingAsync(); Task> GetAllListAsNoTrackingAsync(Expression> predicate); TEntity GetAsNoTracking(TPrimaryKey id); Task GetAsNoTrackingAsync(TPrimaryKey id); TEntity LoadAsNoTracking(TPrimaryKey id); long LongCountAsNoTracking(); long LongCountAsNoTracking(Expression> predicate); Task LongCountAsNoTrackingAsync(); Task LongCountAsNoTrackingAsync(Expression> predicate); T QueryAsNoTracking(Func, T> queryMethod); TEntity SingleAsNoTracking(Expression> predicate); Task SingleAsNoTrackingAsync(Expression> predicate); Task BulkInsert(IList entities); Task BulkUpdate(IList entities); Task BulkDelete(IList entities); } public interface ICustomRepository : ICustomRepository where TEntity : class, IEntity { }
public class CustomRepository : ProjectNameRepositoryBase, ICustomRepository where TEntity : class, IEntity { private readonly IDbContextProvider _dbContextProvider; public CustomRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) { _dbContextProvider = dbContextProvider; } public virtual IQueryable GetAllAsNoTracking() { return GetAll().AsNoTracking(); } public virtual IQueryable GetAllIncludingAsNoTracking(params Expression>[] propertySelectors) { return GetAllAsNoTracking(); } public virtual List GetAllListAsNoTracking() { return GetAllAsNoTracking().ToList(); } public virtual Task> GetAllListAsNoTrackingAsync() { return Task.FromResult(GetAllListAsNoTracking()); } public virtual List GetAllListAsNoTracking(Expression> predicate) { return GetAllAsNoTracking().Where(predicate).ToList(); } public virtual Task> GetAllListAsNoTrackingAsync(Expression> predicate) { return Task.FromResult(GetAllListAsNoTracking(predicate)); } public virtual T QueryAsNoTracking(Func, T> queryMethod) { return queryMethod(GetAllAsNoTracking()); } public virtual TEntity GetAsNoTracking(TPrimaryKey id) { var entity = FirstOrDefaultAsNoTracking(id); if (entity == null) { throw new EntityNotFoundException(typeof(TEntity), id); } return entity; } public virtual async Task GetAsNoTrackingAsync(TPrimaryKey id) { var entity = await FirstOrDefaultAsNoTrackingAsync(id); if (entity == null) { throw new EntityNotFoundException(typeof(TEntity), id); } return entity; } public virtual TEntity SingleAsNoTracking(Expression> predicate) { return GetAllAsNoTracking().Single(predicate); } public virtual Task SingleAsNoTrackingAsync(Expression> predicate) { return Task.FromResult(SingleAsNoTracking(predicate)); } public virtual TEntity FirstOrDefaultAsNoTracking(TPrimaryKey id) { return GetAllAsNoTracking().FirstOrDefault(CreateEqualityExpressionForId(id)); } public virtual Task FirstOrDefaultAsNoTrackingAsync(TPrimaryKey id) { return Task.FromResult(FirstOrDefaultAsNoTracking(id)); } public virtual TEntity FirstOrDefaultAsNoTracking(Expression> predicate) { return GetAllAsNoTracking().FirstOrDefault(predicate); } public virtual Task FirstOrDefaultAsNoTrackingAsync(Expression> predicate) { return Task.FromResult(FirstOrDefaultAsNoTracking(predicate)); } public virtual TEntity LoadAsNoTracking(TPrimaryKey id) { return GetAsNoTracking(id); } public virtual int CountAsNoTracking() { return GetAllAsNoTracking().Count(); } public virtual Task CountAsNoTrackingAsync() { return Task.FromResult(CountAsNoTracking()); } public virtual int CountAsNoTracking(Expression> predicate) { return GetAllAsNoTracking().Where(predicate).Count(); } public virtual Task CountAsNoTrackingAsync(Expression> predicate) { return Task.FromResult(CountAsNoTracking(predicate)); } public virtual long LongCountAsNoTracking() { return GetAllAsNoTracking().LongCount(); } public virtual Task LongCountAsNoTrackingAsync() { return Task.FromResult(LongCountAsNoTracking()); } public virtual long LongCountAsNoTracking(Expression> predicate) { return GetAllAsNoTracking().Where(predicate).LongCount(); } public virtual Task LongCountAsNoTrackingAsync(Expression> predicate) { return Task.FromResult(LongCountAsNoTracking(predicate)); } public virtual async Task BulkInsert(IList entities) { var _context = await _dbContextProvider.GetDbContextAsync(); var bulkConfig = new BulkConfig { BulkCopyTimeout = 0, BatchSize = 4000 }; _context.Database.SetCommandTimeout(600); await _context.BulkInsertAsync(entities, bulkConfig); } public virtual async Task BulkUpdate(IList entities) { var _context = await _dbContextProvider.GetDbContextAsync(); var bulkConfig = new BulkConfig { BulkCopyTimeout = 0, BatchSize = 4000 }; _context.Database.SetCommandTimeout(600); await _context.BulkUpdateAsync(entities, bulkConfig); } public virtual async Task BulkDelete(IList entities) { var _context = await _dbContextProvider.GetDbContextAsync(); var bulkConfig = new BulkConfig { BulkCopyTimeout = 0, BatchSize = 4000 }; _context.Database.SetCommandTimeout(600); await _context.BulkDeleteAsync(entities, bulkConfig); } }
Register this repository on PreInitialize (EntityFrameworkCoreModule):
IocManager.IocContainer.Register(Component.For(typeof(ICustomRepository)).ImplementedBy(typeof(CusomRepository)).LifestyleTransient());
Use:
public class TestAppService : ProjectAppServiceBase, ITestAppService { private readonly ICustomRepository _carRepository; public TestAppService(ICustomRepository carRepository) { _carRepository = carRepository; } public async Task Test(TestInput input) { // do a logic // await _carRepository.BulkInsert(input.cars); } }