Skip to content

Commit

Permalink
(#125) Bulk Insert/Update/Delete/Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
phongnguyend committed Nov 28, 2021
1 parent f753eb8 commit 506d5fd
Show file tree
Hide file tree
Showing 57 changed files with 752 additions and 1,401 deletions.
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -22,5 +24,15 @@ public interface IRepository<TEntity, TKey>
Task<T> SingleOrDefaultAsync<T>(IQueryable<T> query);

Task<List<T>> ToListAsync<T>(IQueryable<T> query);

void BulkInsert(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> columnNamesSelector);

void BulkInsert(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> columnNamesSelector, Expression<Func<TEntity, object>> idSelector);

void BulkUpdate(IList<TEntity> data, Expression<Func<TEntity, object>> idSelector, Expression<Func<TEntity, object>> columnNamesSelector);

void BulkMerge(IEnumerable<TEntity> data, Expression<Func<TEntity, object>> idSelector, Expression<Func<TEntity, object>> updateColumnNamesSelector, Expression<Func<TEntity, object>> insertColumnNamesSelector);

void BulkDelete(IList<TEntity> data, Expression<Func<TEntity, object>> idSelector);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@
<PackageReference Include="Azure.Storage.Queues" Version="12.8.0" />
<PackageReference Include="Castle.Core" Version="4.4.1" />
<PackageReference Include="Confluent.Kafka" Version="1.8.2" />
<PackageReference Include="CryptographyHelper" Version="1.0.0-beta4" />
<PackageReference Include="CryptographyHelper" Version="1.0.0" />
<PackageReference Include="CsvHelper" Version="27.2.0" />
<PackageReference Include="Dapper.StrongName" Version="2.0.123" />
<PackageReference Include="DinkToPdf" Version="1.0.8" />
<PackageReference Include="Google.Protobuf" Version="3.19.1" />
<PackageReference Include="Grpc.Net.Client" Version="2.40.0" />
<PackageReference Include="EntityFrameworkCore.SqlServer.SimpleBulks" Version="6.0.0" />
<PackageReference Include="IdentityModel" Version="5.2.0" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.19.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -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<TDbContext, TEntity, TKey> : IRepository<TEntity, TKey>
where TEntity : AggregateRoot<TKey>
where TDbContext : DbContext, IUnitOfWork
{
private readonly TDbContext _dbContext;
private readonly IDateTimeProvider _dateTimeProvider;

protected DbSet<TEntity> DbSet => _dbContext.Set<TEntity>();

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<TEntity> GetAll()
{
return _dbContext.Set<TEntity>();
}

public Task<T1> FirstOrDefaultAsync<T1>(IQueryable<T1> query)
{
return query.FirstOrDefaultAsync();
}

public Task<T1> SingleOrDefaultAsync<T1>(IQueryable<T1> query)
{
return query.SingleOrDefaultAsync();
}

public Task<List<T1>> ToListAsync<T1>(IQueryable<T1> query)
{
return query.ToListAsync();
}

public void BulkInsert(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> columnNamesSelector)
{
_dbContext.BulkInsert(entities, columnNamesSelector);
}

public void BulkInsert(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> columnNamesSelector, Expression<Func<TEntity, object>> idSelector)
{
_dbContext.BulkInsert(entities, columnNamesSelector, idSelector);
}

public void BulkUpdate(IList<TEntity> data, Expression<Func<TEntity, object>> idSelector, Expression<Func<TEntity, object>> columnNamesSelector)
{
_dbContext.BulkUpdate(data, idSelector, columnNamesSelector);
}

public void BulkDelete(IList<TEntity> data, Expression<Func<TEntity, object>> idSelector)
{
_dbContext.BulkDelete(data, idSelector);
}

public void BulkMerge(IEnumerable<TEntity> data, Expression<Func<TEntity, object>> idSelector, Expression<Func<TEntity, object>> updateColumnNamesSelector, Expression<Func<TEntity, object>> insertColumnNamesSelector)
{
_dbContext.BulkMerge(data, idSelector, updateColumnNamesSelector, insertColumnNamesSelector);
}
}
}
Original file line number Diff line number Diff line change
@@ -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<TDbContext> : DbContext, IUnitOfWork
where TDbContext : DbContext
{
private IDbContextTransaction _dbContextTransaction;

public DbContextUnitOfWork(DbContextOptions<TDbContext> options)
: base(options)
{
}

public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
{
_dbContextTransaction = Database.BeginTransaction(isolationLevel);
return _dbContextTransaction;
}

public async Task<IDisposable> 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());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<CodeAnalysisRuleSet>ClassifiedAds.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<CodeAnalysisRuleSet>ClassifiedAds.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Common\ClassifiedAds.Application\ClassifiedAds.Application.csproj" />
<ProjectReference Include="..\..\Common\ClassifiedAds.CrossCuttingConcerns\ClassifiedAds.CrossCuttingConcerns.csproj" />
<ProjectReference Include="..\..\Common\ClassifiedAds.Domain\ClassifiedAds.Domain.csproj" />
<ProjectReference Include="..\..\Common\ClassifiedAds.Infrastructure\ClassifiedAds.Infrastructure.csproj" />
<ProjectReference Include="..\ClassifiedAds.Services.AuditLog\ClassifiedAds.Services.AuditLog.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\ClassifiedAds.Application\ClassifiedAds.Application.csproj" />
<ProjectReference Include="..\..\Common\ClassifiedAds.CrossCuttingConcerns\ClassifiedAds.CrossCuttingConcerns.csproj" />
<ProjectReference Include="..\..\Common\ClassifiedAds.Domain\ClassifiedAds.Domain.csproj" />
<ProjectReference Include="..\..\Common\ClassifiedAds.Infrastructure\ClassifiedAds.Infrastructure.csproj" />
<ProjectReference Include="..\ClassifiedAds.Services.AuditLog\ClassifiedAds.Services.AuditLog.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Microsoft.Extensions.Hosting;
using Polly;
using System;
using System.Reflection;

namespace ClassifiedAds.Services.AuditLog
{
Expand All @@ -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));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
Expand All @@ -17,10 +17,6 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Polly" Version="7.2.2" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
Expand Down
Original file line number Diff line number Diff line change
@@ -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<AuditLogDbContext>
{
private IDbContextTransaction _dbContextTransaction;

public AuditLogDbContext(DbContextOptions<AuditLogDbContext> options)
: base(options)
{
}

public IDisposable BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
{
_dbContextTransaction = Database.BeginTransaction(isolationLevel);
return _dbContextTransaction;
}

public async Task<IDisposable> 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);
Expand Down
Loading

0 comments on commit 506d5fd

Please sign in to comment.