diff --git a/src/Microservices/Common/ClassifiedAds.Domain/Repositories/IRepository.cs b/src/Microservices/Common/ClassifiedAds.Domain/Repositories/IRepository.cs index f0b5f0c05..8b1cdf71b 100644 --- a/src/Microservices/Common/ClassifiedAds.Domain/Repositories/IRepository.cs +++ b/src/Microservices/Common/ClassifiedAds.Domain/Repositories/IRepository.cs @@ -1,6 +1,8 @@ using ClassifiedAds.Domain.Entities; +using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -22,5 +24,15 @@ public interface IRepository Task SingleOrDefaultAsync(IQueryable query); Task> ToListAsync(IQueryable query); + + void BulkInsert(IEnumerable entities, Expression> columnNamesSelector); + + void BulkInsert(IEnumerable entities, Expression> columnNamesSelector, Expression> idSelector); + + void BulkUpdate(IList data, Expression> idSelector, Expression> columnNamesSelector); + + void BulkMerge(IEnumerable data, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector); + + void BulkDelete(IList data, Expression> idSelector); } } diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj b/src/Microservices/Common/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj index fc01f225e..4203e33e5 100644 --- a/src/Microservices/Common/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj +++ b/src/Microservices/Common/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj @@ -34,12 +34,13 @@ - + + diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/Persistence/DbContextRepository.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/Persistence/DbContextRepository.cs new file mode 100644 index 000000000..36b8b03b4 --- /dev/null +++ b/src/Microservices/Common/ClassifiedAds.Infrastructure/Persistence/DbContextRepository.cs @@ -0,0 +1,104 @@ +using ClassifiedAds.CrossCuttingConcerns.OS; +using ClassifiedAds.Domain.Entities; +using ClassifiedAds.Domain.Repositories; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkDelete; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkInsert; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkMerge; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkUpdate; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; + +namespace ClassifiedAds.Infrastructure.Persistence +{ + public class DbContextRepository : IRepository + where TEntity : AggregateRoot + where TDbContext : DbContext, IUnitOfWork + { + private readonly TDbContext _dbContext; + private readonly IDateTimeProvider _dateTimeProvider; + + protected DbSet DbSet => _dbContext.Set(); + + public IUnitOfWork UnitOfWork + { + get + { + return _dbContext; + } + } + + public DbContextRepository(TDbContext dbContext, IDateTimeProvider dateTimeProvider) + { + _dbContext = dbContext; + _dateTimeProvider = dateTimeProvider; + } + + public async Task AddOrUpdateAsync(TEntity entity, CancellationToken cancellationToken = default) + { + if (entity.Id.Equals(default(TKey))) + { + entity.CreatedDateTime = _dateTimeProvider.OffsetNow; + await DbSet.AddAsync(entity, cancellationToken); + } + else + { + entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; + } + } + + public void Delete(TEntity entity) + { + DbSet.Remove(entity); + } + + public IQueryable GetAll() + { + return _dbContext.Set(); + } + + public Task FirstOrDefaultAsync(IQueryable query) + { + return query.FirstOrDefaultAsync(); + } + + public Task SingleOrDefaultAsync(IQueryable query) + { + return query.SingleOrDefaultAsync(); + } + + public Task> ToListAsync(IQueryable query) + { + return query.ToListAsync(); + } + + public void BulkInsert(IEnumerable entities, Expression> columnNamesSelector) + { + _dbContext.BulkInsert(entities, columnNamesSelector); + } + + public void BulkInsert(IEnumerable entities, Expression> columnNamesSelector, Expression> idSelector) + { + _dbContext.BulkInsert(entities, columnNamesSelector, idSelector); + } + + public void BulkUpdate(IList data, Expression> idSelector, Expression> columnNamesSelector) + { + _dbContext.BulkUpdate(data, idSelector, columnNamesSelector); + } + + public void BulkDelete(IList data, Expression> idSelector) + { + _dbContext.BulkDelete(data, idSelector); + } + + public void BulkMerge(IEnumerable data, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector) + { + _dbContext.BulkMerge(data, idSelector, updateColumnNamesSelector, insertColumnNamesSelector); + } + } +} diff --git a/src/Microservices/Common/ClassifiedAds.Infrastructure/Persistence/DbContextUnitOfWork.cs b/src/Microservices/Common/ClassifiedAds.Infrastructure/Persistence/DbContextUnitOfWork.cs new file mode 100644 index 000000000..46b52ddaa --- /dev/null +++ b/src/Microservices/Common/ClassifiedAds.Infrastructure/Persistence/DbContextUnitOfWork.cs @@ -0,0 +1,50 @@ +using ClassifiedAds.Domain.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; +using System; +using System.Data; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; + +namespace ClassifiedAds.Infrastructure.Persistence +{ + public class DbContextUnitOfWork : DbContext, IUnitOfWork + where TDbContext : DbContext + { + private IDbContextTransaction _dbContextTransaction; + + public DbContextUnitOfWork(DbContextOptions options) + : base(options) + { + } + + public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) + { + _dbContextTransaction = Database.BeginTransaction(isolationLevel); + return _dbContextTransaction; + } + + public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) + { + _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); + return _dbContextTransaction; + } + + public void CommitTransaction() + { + _dbContextTransaction.Commit(); + } + + public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) + { + await _dbContextTransaction.CommitAsync(cancellationToken); + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); + } + } +} \ No newline at end of file diff --git a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog.Api/ClassifiedAds.Services.AuditLog.Api.csproj b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog.Api/ClassifiedAds.Services.AuditLog.Api.csproj index 5678ae1f7..25b43f5a1 100644 --- a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog.Api/ClassifiedAds.Services.AuditLog.Api.csproj +++ b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog.Api/ClassifiedAds.Services.AuditLog.Api.csproj @@ -1,24 +1,28 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - - + + + + + + + diff --git a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog.Api/Startup.cs b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog.Api/Startup.cs index a47fe4267..a68c9d0b9 100644 --- a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog.Api/Startup.cs +++ b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog.Api/Startup.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Hosting; using Polly; using System; +using System.Reflection; namespace ClassifiedAds.Services.AuditLog { @@ -31,6 +32,8 @@ public Startup(IConfiguration configuration, IWebHostEnvironment env) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + AppSettings.ConnectionStrings.MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; + services.AddControllers(configure => { configure.Filters.Add(typeof(GlobalExceptionFilter)); diff --git a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/ClassifiedAds.Services.AuditLog.csproj b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/ClassifiedAds.Services.AuditLog.csproj index 9bf7fff97..0af0e61b2 100644 --- a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/ClassifiedAds.Services.AuditLog.csproj +++ b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/ClassifiedAds.Services.AuditLog.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -17,10 +17,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - all diff --git a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/Repositories/AuditLogDbContext.cs b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/Repositories/AuditLogDbContext.cs index d5c683e21..64836e5e0 100644 --- a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/Repositories/AuditLogDbContext.cs +++ b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/Repositories/AuditLogDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Services.AuditLog.Repositories { - public class AuditLogDbContext : DbContext, IUnitOfWork + public class AuditLogDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public AuditLogDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/Repositories/Repository.cs b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/Repositories/Repository.cs index 78ffc8975..fbd4a7619 100644 --- a/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/Repositories/Repository.cs +++ b/src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Services.AuditLog.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - private readonly AuditLogDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(AuditLogDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/ClassifiedAds.Services.Configuration.Api.csproj b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/ClassifiedAds.Services.Configuration.Api.csproj index 72b756608..49872847e 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/ClassifiedAds.Services.Configuration.Api.csproj +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/ClassifiedAds.Services.Configuration.Api.csproj @@ -1,40 +1,40 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - + + + + + + - - - Always - - + + + Always + + diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Repositories/ConfigurationDbContext.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Repositories/ConfigurationDbContext.cs index 20c7474a8..ea28d6c22 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Repositories/ConfigurationDbContext.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Repositories/ConfigurationDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Services.Configuration.Repositories { - public class ConfigurationDbContext : DbContext, IUnitOfWork + public class ConfigurationDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public ConfigurationDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Repositories/Repository.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Repositories/Repository.cs index 1ecf6b3bf..801b4d707 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Repositories/Repository.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Services.Configuration.Repositories { - public class Repository : IRepository - where T : AggregateRoot + public class Repository : DbContextRepository + where T : AggregateRoot { - private readonly ConfigurationDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(ConfigurationDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Startup.cs b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Startup.cs index 3235ce5c5..aea45e232 100644 --- a/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Startup.cs +++ b/src/Microservices/Services.Configuration/ClassifiedAds.Services.Configuration.Api/Startup.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Hosting; using Polly; using System; +using System.Reflection; namespace ClassifiedAds.Services.Configuration.Api { @@ -30,6 +31,8 @@ public Startup(IConfiguration configuration, IWebHostEnvironment env) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + AppSettings.ConnectionStrings.MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; + services.Configure(Configuration); services.AddControllers(configure => diff --git a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity.Api/ClassifiedAds.Services.Identity.Api.csproj b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity.Api/ClassifiedAds.Services.Identity.Api.csproj index 991612fc4..b42c20878 100644 --- a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity.Api/ClassifiedAds.Services.Identity.Api.csproj +++ b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity.Api/ClassifiedAds.Services.Identity.Api.csproj @@ -1,24 +1,28 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - - + + + + + + + diff --git a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity.Api/Startup.cs b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity.Api/Startup.cs index b0995fc65..0f4bef680 100644 --- a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity.Api/Startup.cs +++ b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity.Api/Startup.cs @@ -12,6 +12,7 @@ using Microsoft.Extensions.Hosting; using Polly; using System; +using System.Reflection; namespace ClassifiedAds.Services.Identity { @@ -33,6 +34,8 @@ public Startup(IConfiguration configuration, IWebHostEnvironment env) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + AppSettings.ConnectionStrings.MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; + services.AddControllers(configure => { configure.Filters.Add(typeof(GlobalExceptionFilter)); diff --git a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/ClassifiedAds.Services.Identity.csproj b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/ClassifiedAds.Services.Identity.csproj index ba64b653c..93e9b11ac 100644 --- a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/ClassifiedAds.Services.Identity.csproj +++ b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/ClassifiedAds.Services.Identity.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -18,10 +18,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - all diff --git a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/Repositories/IdentityDbContext.cs b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/Repositories/IdentityDbContext.cs index f6ec9db7d..968b0d270 100644 --- a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/Repositories/IdentityDbContext.cs +++ b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/Repositories/IdentityDbContext.cs @@ -1,48 +1,19 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Services.Identity.Repositories { - public class IdentityDbContext : DbContext, IUnitOfWork, IDataProtectionKeyContext + public class IdentityDbContext : DbContextUnitOfWork, IDataProtectionKeyContext { - private IDbContextTransaction _dbContextTransaction; + public DbSet DataProtectionKeys { get; set; } public IdentityDbContext(DbContextOptions options) : base(options) { } - public DbSet DataProtectionKeys { get; set; } - - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/Repositories/Repository.cs b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/Repositories/Repository.cs index 69e613ecc..bf42c5d61 100644 --- a/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/Repositories/Repository.cs +++ b/src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Services.Identity.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - private readonly IdentityDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(IdentityDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification.Api/ClassifiedAds.Services.Notification.Api.csproj b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification.Api/ClassifiedAds.Services.Notification.Api.csproj index a332fd4fa..69a496bff 100644 --- a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification.Api/ClassifiedAds.Services.Notification.Api.csproj +++ b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification.Api/ClassifiedAds.Services.Notification.Api.csproj @@ -1,24 +1,28 @@  - - net6.0 - ClassifiedAds.ruleset - 3bb18abd-09c2-44f2-900e-28cc944866e1 - + + net6.0 + ClassifiedAds.ruleset + 3bb18abd-09c2-44f2-900e-28cc944866e1 + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - - + + + + + + + diff --git a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification.Api/Startup.cs b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification.Api/Startup.cs index 0fc163506..d3dec0454 100644 --- a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification.Api/Startup.cs +++ b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification.Api/Startup.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Hosting; using Polly; using System; +using System.Reflection; namespace ClassifiedAds.Services.Notification { @@ -32,6 +33,8 @@ public Startup(IConfiguration configuration, IWebHostEnvironment env) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + AppSettings.ConnectionStrings.MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; + services.AddControllers(configure => { configure.Filters.Add(typeof(GlobalExceptionFilter)); diff --git a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/ClassifiedAds.Services.Notification.csproj b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/ClassifiedAds.Services.Notification.csproj index 091ced0eb..98bf78069 100644 --- a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/ClassifiedAds.Services.Notification.csproj +++ b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/ClassifiedAds.Services.Notification.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -10,10 +10,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - all diff --git a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/Repositories/NotificationDbContext.cs b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/Repositories/NotificationDbContext.cs index 5fe5cb799..758826f5a 100644 --- a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/Repositories/NotificationDbContext.cs +++ b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/Repositories/NotificationDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Services.Notification.Repositories { - public class NotificationDbContext : DbContext, IUnitOfWork + public class NotificationDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public NotificationDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/Repositories/Repository.cs b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/Repositories/Repository.cs index e876197ad..f4e46a7e0 100644 --- a/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/Repositories/Repository.cs +++ b/src/Microservices/Services.Notification/ClassifiedAds.Services.Notification/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Services.Notification.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - protected readonly NotificationDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(NotificationDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/ClassifiedAds.Services.Product.Api.csproj b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/ClassifiedAds.Services.Product.Api.csproj index 4d4c9df71..862f84a97 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/ClassifiedAds.Services.Product.Api.csproj +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/ClassifiedAds.Services.Product.Api.csproj @@ -1,47 +1,47 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - + + + + + + - - true - true - - - - - PreserveNewest - - + + true + true + + + + + PreserveNewest + + diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Repositories/ProductDbContext.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Repositories/ProductDbContext.cs index 173c2e0ad..60b3cd6ca 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Repositories/ProductDbContext.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Repositories/ProductDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Services.Product.Repositories { - public class ProductDbContext : DbContext, IUnitOfWork + public class ProductDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public ProductDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Repositories/Repository.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Repositories/Repository.cs index 00caec0b6..477327dcd 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Repositories/Repository.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Services.Product.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - private readonly ProductDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(ProductDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Startup.cs b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Startup.cs index 3f530e59b..4464d2deb 100644 --- a/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Startup.cs +++ b/src/Microservices/Services.Product/ClassifiedAds.Services.Product.Api/Startup.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.Hosting; using Polly; using System; +using System.Reflection; namespace ClassifiedAds.Services.Product { @@ -31,6 +32,8 @@ public Startup(IConfiguration configuration, IWebHostEnvironment env) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + AppSettings.ConnectionStrings.MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; + services.AddControllers(configure => { configure.Filters.Add(typeof(GlobalExceptionFilter)); diff --git a/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/ClassifiedAds.Services.Storage.Api.csproj b/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/ClassifiedAds.Services.Storage.Api.csproj index a060aca21..873863b16 100644 --- a/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/ClassifiedAds.Services.Storage.Api.csproj +++ b/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/ClassifiedAds.Services.Storage.Api.csproj @@ -1,36 +1,36 @@  - - net6.0 - ClassifiedAds.ruleset - f2e298d9-f756-4769-92a2-d920b7e1a422 - + + net6.0 + ClassifiedAds.ruleset + f2e298d9-f756-4769-92a2-d920b7e1a422 + - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - + + + + + + diff --git a/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Repositories/Repository.cs b/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Repositories/Repository.cs index 6279747df..0fff9b8ac 100644 --- a/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Repositories/Repository.cs +++ b/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Services.Storage.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - private readonly StorageDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(StorageDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Repositories/StorageDbContext.cs b/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Repositories/StorageDbContext.cs index f8a82fab2..d6a579ae0 100644 --- a/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Repositories/StorageDbContext.cs +++ b/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Repositories/StorageDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Services.Storage.Repositories { - public class StorageDbContext : DbContext, IUnitOfWork + public class StorageDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public StorageDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Startup.cs b/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Startup.cs index e39120301..a6f145462 100644 --- a/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Startup.cs +++ b/src/Microservices/Services.Storage/ClassifiedAds.Services.Storage.Api/Startup.cs @@ -12,6 +12,7 @@ using Microsoft.Extensions.Hosting; using Polly; using System; +using System.Reflection; using System.Threading.Tasks; namespace ClassifiedAds.Services.Storage @@ -34,6 +35,8 @@ public Startup(IConfiguration configuration, IWebHostEnvironment env) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { + AppSettings.ConnectionStrings.MigrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; + services.AddControllers(configure => { configure.Filters.Add(typeof(GlobalExceptionFilter)); diff --git a/src/ModularMonolith/ClassifiedAds.Domain/Repositories/IRepository.cs b/src/ModularMonolith/ClassifiedAds.Domain/Repositories/IRepository.cs index f0b5f0c05..8b1cdf71b 100644 --- a/src/ModularMonolith/ClassifiedAds.Domain/Repositories/IRepository.cs +++ b/src/ModularMonolith/ClassifiedAds.Domain/Repositories/IRepository.cs @@ -1,6 +1,8 @@ using ClassifiedAds.Domain.Entities; +using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -22,5 +24,15 @@ public interface IRepository Task SingleOrDefaultAsync(IQueryable query); Task> ToListAsync(IQueryable query); + + void BulkInsert(IEnumerable entities, Expression> columnNamesSelector); + + void BulkInsert(IEnumerable entities, Expression> columnNamesSelector, Expression> idSelector); + + void BulkUpdate(IList data, Expression> idSelector, Expression> columnNamesSelector); + + void BulkMerge(IEnumerable data, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector); + + void BulkDelete(IList data, Expression> idSelector); } } diff --git a/src/ModularMonolith/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj b/src/ModularMonolith/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj index 126f2c06f..79b97b5d8 100644 --- a/src/ModularMonolith/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj +++ b/src/ModularMonolith/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj @@ -34,10 +34,11 @@ - + + diff --git a/src/ModularMonolith/ClassifiedAds.Infrastructure/Persistence/DbContextRepository.cs b/src/ModularMonolith/ClassifiedAds.Infrastructure/Persistence/DbContextRepository.cs new file mode 100644 index 000000000..36b8b03b4 --- /dev/null +++ b/src/ModularMonolith/ClassifiedAds.Infrastructure/Persistence/DbContextRepository.cs @@ -0,0 +1,104 @@ +using ClassifiedAds.CrossCuttingConcerns.OS; +using ClassifiedAds.Domain.Entities; +using ClassifiedAds.Domain.Repositories; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkDelete; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkInsert; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkMerge; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkUpdate; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading; +using System.Threading.Tasks; + +namespace ClassifiedAds.Infrastructure.Persistence +{ + public class DbContextRepository : IRepository + where TEntity : AggregateRoot + where TDbContext : DbContext, IUnitOfWork + { + private readonly TDbContext _dbContext; + private readonly IDateTimeProvider _dateTimeProvider; + + protected DbSet DbSet => _dbContext.Set(); + + public IUnitOfWork UnitOfWork + { + get + { + return _dbContext; + } + } + + public DbContextRepository(TDbContext dbContext, IDateTimeProvider dateTimeProvider) + { + _dbContext = dbContext; + _dateTimeProvider = dateTimeProvider; + } + + public async Task AddOrUpdateAsync(TEntity entity, CancellationToken cancellationToken = default) + { + if (entity.Id.Equals(default(TKey))) + { + entity.CreatedDateTime = _dateTimeProvider.OffsetNow; + await DbSet.AddAsync(entity, cancellationToken); + } + else + { + entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; + } + } + + public void Delete(TEntity entity) + { + DbSet.Remove(entity); + } + + public IQueryable GetAll() + { + return _dbContext.Set(); + } + + public Task FirstOrDefaultAsync(IQueryable query) + { + return query.FirstOrDefaultAsync(); + } + + public Task SingleOrDefaultAsync(IQueryable query) + { + return query.SingleOrDefaultAsync(); + } + + public Task> ToListAsync(IQueryable query) + { + return query.ToListAsync(); + } + + public void BulkInsert(IEnumerable entities, Expression> columnNamesSelector) + { + _dbContext.BulkInsert(entities, columnNamesSelector); + } + + public void BulkInsert(IEnumerable entities, Expression> columnNamesSelector, Expression> idSelector) + { + _dbContext.BulkInsert(entities, columnNamesSelector, idSelector); + } + + public void BulkUpdate(IList data, Expression> idSelector, Expression> columnNamesSelector) + { + _dbContext.BulkUpdate(data, idSelector, columnNamesSelector); + } + + public void BulkDelete(IList data, Expression> idSelector) + { + _dbContext.BulkDelete(data, idSelector); + } + + public void BulkMerge(IEnumerable data, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector) + { + _dbContext.BulkMerge(data, idSelector, updateColumnNamesSelector, insertColumnNamesSelector); + } + } +} diff --git a/src/ModularMonolith/ClassifiedAds.Infrastructure/Persistence/DbContextUnitOfWork.cs b/src/ModularMonolith/ClassifiedAds.Infrastructure/Persistence/DbContextUnitOfWork.cs new file mode 100644 index 000000000..46b52ddaa --- /dev/null +++ b/src/ModularMonolith/ClassifiedAds.Infrastructure/Persistence/DbContextUnitOfWork.cs @@ -0,0 +1,50 @@ +using ClassifiedAds.Domain.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; +using System; +using System.Data; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; + +namespace ClassifiedAds.Infrastructure.Persistence +{ + public class DbContextUnitOfWork : DbContext, IUnitOfWork + where TDbContext : DbContext + { + private IDbContextTransaction _dbContextTransaction; + + public DbContextUnitOfWork(DbContextOptions options) + : base(options) + { + } + + public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) + { + _dbContextTransaction = Database.BeginTransaction(isolationLevel); + return _dbContextTransaction; + } + + public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) + { + _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); + return _dbContextTransaction; + } + + public void CommitTransaction() + { + _dbContextTransaction.Commit(); + } + + public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) + { + await _dbContextTransaction.CommitAsync(cancellationToken); + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); + } + } +} \ No newline at end of file diff --git a/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/ClassifiedAds.Modules.AuditLog.csproj b/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/ClassifiedAds.Modules.AuditLog.csproj index 01b005a0a..022566044 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/ClassifiedAds.Modules.AuditLog.csproj +++ b/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/ClassifiedAds.Modules.AuditLog.csproj @@ -1,27 +1,25 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - - - + + + + + + + + diff --git a/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/Repositories/AuditLogDbContext.cs b/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/Repositories/AuditLogDbContext.cs index 62e691412..b66c2b09d 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/Repositories/AuditLogDbContext.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/Repositories/AuditLogDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Modules.AuditLog.Repositories { - public class AuditLogDbContext : DbContext, IUnitOfWork + public class AuditLogDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public AuditLogDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/Repositories/Repository.cs b/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/Repositories/Repository.cs index d2b928265..4c337c2ef 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/Repositories/Repository.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.AuditLog/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Modules.AuditLog.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - private readonly AuditLogDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(AuditLogDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Configuration/ClassifiedAds.Modules.Configuration.csproj b/src/ModularMonolith/ClassifiedAds.Modules.Configuration/ClassifiedAds.Modules.Configuration.csproj index 93287f4e0..157177802 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Configuration/ClassifiedAds.Modules.Configuration.csproj +++ b/src/ModularMonolith/ClassifiedAds.Modules.Configuration/ClassifiedAds.Modules.Configuration.csproj @@ -1,29 +1,26 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - + + + + + + diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Configuration/Repositories/ConfigurationDbContext.cs b/src/ModularMonolith/ClassifiedAds.Modules.Configuration/Repositories/ConfigurationDbContext.cs index 3cd013315..dc52480cb 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Configuration/Repositories/ConfigurationDbContext.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Configuration/Repositories/ConfigurationDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Modules.Configuration.Repositories { - public class ConfigurationDbContext : DbContext, IUnitOfWork + public class ConfigurationDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public ConfigurationDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Configuration/Repositories/Repository.cs b/src/ModularMonolith/ClassifiedAds.Modules.Configuration/Repositories/Repository.cs index 1b520699a..23c0fb031 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Configuration/Repositories/Repository.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Configuration/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Modules.Configuration.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - private readonly ConfigurationDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(ConfigurationDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Identity/ClassifiedAds.Modules.Identity.csproj b/src/ModularMonolith/ClassifiedAds.Modules.Identity/ClassifiedAds.Modules.Identity.csproj index 0d5201079..a48489728 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Identity/ClassifiedAds.Modules.Identity.csproj +++ b/src/ModularMonolith/ClassifiedAds.Modules.Identity/ClassifiedAds.Modules.Identity.csproj @@ -1,28 +1,26 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - - - + + + + + + + + diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Identity/Repositories/IdentityDbContext.cs b/src/ModularMonolith/ClassifiedAds.Modules.Identity/Repositories/IdentityDbContext.cs index 8ddb92595..960ca717b 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Identity/Repositories/IdentityDbContext.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Identity/Repositories/IdentityDbContext.cs @@ -1,48 +1,19 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Modules.Identity.Repositories { - public class IdentityDbContext : DbContext, IUnitOfWork, IDataProtectionKeyContext + public class IdentityDbContext : DbContextUnitOfWork, IDataProtectionKeyContext { - private IDbContextTransaction _dbContextTransaction; + public DbSet DataProtectionKeys { get; set; } public IdentityDbContext(DbContextOptions options) : base(options) { } - public DbSet DataProtectionKeys { get; set; } - - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Identity/Repositories/Repository.cs b/src/ModularMonolith/ClassifiedAds.Modules.Identity/Repositories/Repository.cs index c728a13e1..db15bde92 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Identity/Repositories/Repository.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Identity/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Modules.Identity.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - private readonly IdentityDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(IdentityDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Notification/ClassifiedAds.Modules.Notification.csproj b/src/ModularMonolith/ClassifiedAds.Modules.Notification/ClassifiedAds.Modules.Notification.csproj index abab14766..cf578a967 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Notification/ClassifiedAds.Modules.Notification.csproj +++ b/src/ModularMonolith/ClassifiedAds.Modules.Notification/ClassifiedAds.Modules.Notification.csproj @@ -1,26 +1,24 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + - - - - - - - - diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Notification/Repositories/NotificationDbContext.cs b/src/ModularMonolith/ClassifiedAds.Modules.Notification/Repositories/NotificationDbContext.cs index 6a7ca2f4e..d047ca6da 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Notification/Repositories/NotificationDbContext.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Notification/Repositories/NotificationDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Modules.Notification.Repositories { - public class NotificationDbContext : DbContext, IUnitOfWork + public class NotificationDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public NotificationDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Notification/Repositories/Repository.cs b/src/ModularMonolith/ClassifiedAds.Modules.Notification/Repositories/Repository.cs index 42d034a0e..56c767430 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Notification/Repositories/Repository.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Notification/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Modules.Notification.Repositories { - public class Repository : IRepository - where T : AggregateRoot + public class Repository : DbContextRepository + where T : AggregateRoot { - protected readonly NotificationDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(NotificationDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Product/ClassifiedAds.Modules.Product.csproj b/src/ModularMonolith/ClassifiedAds.Modules.Product/ClassifiedAds.Modules.Product.csproj index 01b005a0a..022566044 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Product/ClassifiedAds.Modules.Product.csproj +++ b/src/ModularMonolith/ClassifiedAds.Modules.Product/ClassifiedAds.Modules.Product.csproj @@ -1,27 +1,25 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - - - + + + + + + + + diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Product/Repositories/ProductDbContext.cs b/src/ModularMonolith/ClassifiedAds.Modules.Product/Repositories/ProductDbContext.cs index 9f0640087..a1158df40 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Product/Repositories/ProductDbContext.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Product/Repositories/ProductDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Modules.Product.Repositories { - public class ProductDbContext : DbContext, IUnitOfWork + public class ProductDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public ProductDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Product/Repositories/Repository.cs b/src/ModularMonolith/ClassifiedAds.Modules.Product/Repositories/Repository.cs index f74f37193..dd998faf2 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Product/Repositories/Repository.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Product/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Modules.Product.Repositories { - public class Repository : IRepository + public class Repository : DbContextRepository where T : AggregateRoot { - private readonly ProductDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(ProductDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Storage/ClassifiedAds.Modules.Storage.csproj b/src/ModularMonolith/ClassifiedAds.Modules.Storage/ClassifiedAds.Modules.Storage.csproj index 01b005a0a..022566044 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Storage/ClassifiedAds.Modules.Storage.csproj +++ b/src/ModularMonolith/ClassifiedAds.Modules.Storage/ClassifiedAds.Modules.Storage.csproj @@ -1,27 +1,25 @@  - - net6.0 - ClassifiedAds.ruleset - + + net6.0 + ClassifiedAds.ruleset + - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - - - - - - + + + + + + + + diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Storage/Repositories/Repository.cs b/src/ModularMonolith/ClassifiedAds.Modules.Storage/Repositories/Repository.cs index 6700a6857..d6285d5da 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Storage/Repositories/Repository.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Storage/Repositories/Repository.cs @@ -1,72 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; -using ClassifiedAds.Domain.Repositories; -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using ClassifiedAds.Infrastructure.Persistence; namespace ClassifiedAds.Modules.Storage.Repositories { - public class Repository : IRepository - where T : AggregateRoot + public class Repository : DbContextRepository + where T : AggregateRoot { - private readonly StorageDbContext _dbContext; - private readonly IDateTimeProvider _dateTimeProvider; - - protected DbSet DbSet => _dbContext.Set(); - - public IUnitOfWork UnitOfWork - { - get - { - return _dbContext; - } - } - public Repository(StorageDbContext dbContext, IDateTimeProvider dateTimeProvider) + : base(dbContext, dateTimeProvider) { - _dbContext = dbContext; - _dateTimeProvider = dateTimeProvider; - } - - public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default) - { - if (entity.Id.Equals(default(TKey))) - { - entity.CreatedDateTime = _dateTimeProvider.OffsetNow; - await DbSet.AddAsync(entity, cancellationToken); - } - else - { - entity.UpdatedDateTime = _dateTimeProvider.OffsetNow; - } - } - - public void Delete(T entity) - { - DbSet.Remove(entity); - } - - public IQueryable GetAll() - { - return _dbContext.Set(); - } - - public Task FirstOrDefaultAsync(IQueryable query) - { - return query.FirstOrDefaultAsync(); - } - - public Task SingleOrDefaultAsync(IQueryable query) - { - return query.SingleOrDefaultAsync(); - } - - public Task> ToListAsync(IQueryable query) - { - return query.ToListAsync(); } } } diff --git a/src/ModularMonolith/ClassifiedAds.Modules.Storage/Repositories/StorageDbContext.cs b/src/ModularMonolith/ClassifiedAds.Modules.Storage/Repositories/StorageDbContext.cs index 8e329d333..6ffcdfffd 100644 --- a/src/ModularMonolith/ClassifiedAds.Modules.Storage/Repositories/StorageDbContext.cs +++ b/src/ModularMonolith/ClassifiedAds.Modules.Storage/Repositories/StorageDbContext.cs @@ -1,45 +1,16 @@ -using ClassifiedAds.Domain.Repositories; +using ClassifiedAds.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; -using System; -using System.Data; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; namespace ClassifiedAds.Modules.Storage.Repositories { - public class StorageDbContext : DbContext, IUnitOfWork + public class StorageDbContext : DbContextUnitOfWork { - private IDbContextTransaction _dbContextTransaction; - public StorageDbContext(DbContextOptions options) : base(options) { } - public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted) - { - _dbContextTransaction = Database.BeginTransaction(isolationLevel); - return _dbContextTransaction; - } - - public async Task BeginTransactionAsync(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted, CancellationToken cancellationToken = default) - { - _dbContextTransaction = await Database.BeginTransactionAsync(isolationLevel, cancellationToken); - return _dbContextTransaction; - } - - public void CommitTransaction() - { - _dbContextTransaction.Commit(); - } - - public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) - { - await _dbContextTransaction.CommitAsync(cancellationToken); - } - protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); diff --git a/src/Monolith/ClassifiedAds.Domain/Repositories/IRepository.cs b/src/Monolith/ClassifiedAds.Domain/Repositories/IRepository.cs index f0b5f0c05..8b1cdf71b 100644 --- a/src/Monolith/ClassifiedAds.Domain/Repositories/IRepository.cs +++ b/src/Monolith/ClassifiedAds.Domain/Repositories/IRepository.cs @@ -1,6 +1,8 @@ using ClassifiedAds.Domain.Entities; +using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -22,5 +24,15 @@ public interface IRepository Task SingleOrDefaultAsync(IQueryable query); Task> ToListAsync(IQueryable query); + + void BulkInsert(IEnumerable entities, Expression> columnNamesSelector); + + void BulkInsert(IEnumerable entities, Expression> columnNamesSelector, Expression> idSelector); + + void BulkUpdate(IList data, Expression> idSelector, Expression> columnNamesSelector); + + void BulkMerge(IEnumerable data, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector); + + void BulkDelete(IList data, Expression> idSelector); } } diff --git a/src/Monolith/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj b/src/Monolith/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj index 463731fc3..6f737d314 100644 --- a/src/Monolith/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj +++ b/src/Monolith/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj @@ -35,7 +35,7 @@ - + diff --git a/src/Monolith/ClassifiedAds.Persistence/ClassifiedAds.Persistence.csproj b/src/Monolith/ClassifiedAds.Persistence/ClassifiedAds.Persistence.csproj index 708ddf5ba..fdd121110 100644 --- a/src/Monolith/ClassifiedAds.Persistence/ClassifiedAds.Persistence.csproj +++ b/src/Monolith/ClassifiedAds.Persistence/ClassifiedAds.Persistence.csproj @@ -7,6 +7,7 @@ + diff --git a/src/Monolith/ClassifiedAds.Persistence/Repositories/Repository.cs b/src/Monolith/ClassifiedAds.Persistence/Repositories/Repository.cs index 9b3e7d3d9..a8ac305fd 100644 --- a/src/Monolith/ClassifiedAds.Persistence/Repositories/Repository.cs +++ b/src/Monolith/ClassifiedAds.Persistence/Repositories/Repository.cs @@ -1,9 +1,15 @@ using ClassifiedAds.CrossCuttingConcerns.OS; using ClassifiedAds.Domain.Entities; using ClassifiedAds.Domain.Repositories; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkDelete; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkInsert; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkMerge; +using EntityFrameworkCore.SqlServer.SimpleBulks.BulkUpdate; using Microsoft.EntityFrameworkCore; +using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; @@ -68,5 +74,30 @@ public Task> ToListAsync(IQueryable query) { return query.ToListAsync(); } + + public void BulkInsert(IEnumerable entities, Expression> columnNamesSelector) + { + _dbContext.BulkInsert(entities, columnNamesSelector); + } + + public void BulkInsert(IEnumerable entities, Expression> columnNamesSelector, Expression> idSelector) + { + _dbContext.BulkInsert(entities, columnNamesSelector, idSelector); + } + + public void BulkUpdate(IList data, Expression> idSelector, Expression> columnNamesSelector) + { + _dbContext.BulkUpdate(data, idSelector, columnNamesSelector); + } + + public void BulkDelete(IList data, Expression> idSelector) + { + _dbContext.BulkDelete(data, idSelector); + } + + public void BulkMerge(IEnumerable data, Expression> idSelector, Expression> updateColumnNamesSelector, Expression> insertColumnNamesSelector) + { + _dbContext.BulkMerge(data, idSelector, updateColumnNamesSelector, insertColumnNamesSelector); + } } }