Skip to content

Commit 1ebc0ea

Browse files
committed
(#125) Bulk Insert/Update/Delete/Merge
1 parent f753eb8 commit 1ebc0ea

File tree

34 files changed

+542
-961
lines changed

34 files changed

+542
-961
lines changed

src/Microservices/Common/ClassifiedAds.Domain/Repositories/IRepository.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using ClassifiedAds.Domain.Entities;
2+
using System;
23
using System.Collections.Generic;
34
using System.Linq;
5+
using System.Linq.Expressions;
46
using System.Threading;
57
using System.Threading.Tasks;
68

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

2426
Task<List<T>> ToListAsync<T>(IQueryable<T> query);
27+
28+
void BulkInsert(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> columnNamesSelector);
29+
30+
void BulkInsert(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> columnNamesSelector, Expression<Func<TEntity, object>> idSelector);
31+
32+
void BulkUpdate(IList<TEntity> data, Expression<Func<TEntity, object>> idSelector, Expression<Func<TEntity, object>> columnNamesSelector);
33+
34+
void BulkMerge(IEnumerable<TEntity> data, Expression<Func<TEntity, object>> idSelector, Expression<Func<TEntity, object>> updateColumnNamesSelector, Expression<Func<TEntity, object>> insertColumnNamesSelector);
35+
36+
void BulkDelete(IList<TEntity> data, Expression<Func<TEntity, object>> idSelector);
2537
}
2638
}

src/Microservices/Common/ClassifiedAds.Infrastructure/ClassifiedAds.Infrastructure.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,13 @@
3434
<PackageReference Include="Azure.Storage.Queues" Version="12.8.0" />
3535
<PackageReference Include="Castle.Core" Version="4.4.1" />
3636
<PackageReference Include="Confluent.Kafka" Version="1.8.2" />
37-
<PackageReference Include="CryptographyHelper" Version="1.0.0-beta4" />
37+
<PackageReference Include="CryptographyHelper" Version="1.0.0" />
3838
<PackageReference Include="CsvHelper" Version="27.2.0" />
3939
<PackageReference Include="Dapper.StrongName" Version="2.0.123" />
4040
<PackageReference Include="DinkToPdf" Version="1.0.8" />
4141
<PackageReference Include="Google.Protobuf" Version="3.19.1" />
4242
<PackageReference Include="Grpc.Net.Client" Version="2.40.0" />
43+
<PackageReference Include="EntityFrameworkCore.SqlServer.SimpleBulks" Version="6.0.0" />
4344
<PackageReference Include="IdentityModel" Version="5.2.0" />
4445
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.19.0" />
4546
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.0" />
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using ClassifiedAds.CrossCuttingConcerns.OS;
2+
using ClassifiedAds.Domain.Entities;
3+
using ClassifiedAds.Domain.Repositories;
4+
using EntityFrameworkCore.SqlServer.SimpleBulks.BulkDelete;
5+
using EntityFrameworkCore.SqlServer.SimpleBulks.BulkInsert;
6+
using EntityFrameworkCore.SqlServer.SimpleBulks.BulkMerge;
7+
using EntityFrameworkCore.SqlServer.SimpleBulks.BulkUpdate;
8+
using Microsoft.EntityFrameworkCore;
9+
using System;
10+
using System.Collections.Generic;
11+
using System.Linq;
12+
using System.Linq.Expressions;
13+
using System.Threading;
14+
using System.Threading.Tasks;
15+
16+
namespace ClassifiedAds.Infrastructure.Persistence
17+
{
18+
public class DbContextRepository<TDbContext, TEntity, TKey> : IRepository<TEntity, TKey>
19+
where TEntity : AggregateRoot<TKey>
20+
where TDbContext : DbContext, IUnitOfWork
21+
{
22+
private readonly TDbContext _dbContext;
23+
private readonly IDateTimeProvider _dateTimeProvider;
24+
25+
protected DbSet<TEntity> DbSet => _dbContext.Set<TEntity>();
26+
27+
public IUnitOfWork UnitOfWork
28+
{
29+
get
30+
{
31+
return _dbContext;
32+
}
33+
}
34+
35+
public DbContextRepository(TDbContext dbContext, IDateTimeProvider dateTimeProvider)
36+
{
37+
_dbContext = dbContext;
38+
_dateTimeProvider = dateTimeProvider;
39+
}
40+
41+
public async Task AddOrUpdateAsync(TEntity entity, CancellationToken cancellationToken = default)
42+
{
43+
if (entity.Id.Equals(default(TKey)))
44+
{
45+
entity.CreatedDateTime = _dateTimeProvider.OffsetNow;
46+
await DbSet.AddAsync(entity, cancellationToken);
47+
}
48+
else
49+
{
50+
entity.UpdatedDateTime = _dateTimeProvider.OffsetNow;
51+
}
52+
}
53+
54+
public void Delete(TEntity entity)
55+
{
56+
DbSet.Remove(entity);
57+
}
58+
59+
public IQueryable<TEntity> GetAll()
60+
{
61+
return _dbContext.Set<TEntity>();
62+
}
63+
64+
public Task<T1> FirstOrDefaultAsync<T1>(IQueryable<T1> query)
65+
{
66+
return query.FirstOrDefaultAsync();
67+
}
68+
69+
public Task<T1> SingleOrDefaultAsync<T1>(IQueryable<T1> query)
70+
{
71+
return query.SingleOrDefaultAsync();
72+
}
73+
74+
public Task<List<T1>> ToListAsync<T1>(IQueryable<T1> query)
75+
{
76+
return query.ToListAsync();
77+
}
78+
79+
public void BulkInsert(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> columnNamesSelector)
80+
{
81+
_dbContext.BulkInsert(entities, columnNamesSelector);
82+
}
83+
84+
public void BulkInsert(IEnumerable<TEntity> entities, Expression<Func<TEntity, object>> columnNamesSelector, Expression<Func<TEntity, object>> idSelector)
85+
{
86+
_dbContext.BulkInsert(entities, columnNamesSelector, idSelector);
87+
}
88+
89+
public void BulkUpdate(IList<TEntity> data, Expression<Func<TEntity, object>> idSelector, Expression<Func<TEntity, object>> columnNamesSelector)
90+
{
91+
_dbContext.BulkUpdate(data, idSelector, columnNamesSelector);
92+
}
93+
94+
public void BulkDelete(IList<TEntity> data, Expression<Func<TEntity, object>> idSelector)
95+
{
96+
_dbContext.BulkDelete(data, idSelector);
97+
}
98+
99+
public void BulkMerge(IEnumerable<TEntity> data, Expression<Func<TEntity, object>> idSelector, Expression<Func<TEntity, object>> updateColumnNamesSelector, Expression<Func<TEntity, object>> insertColumnNamesSelector)
100+
{
101+
_dbContext.BulkMerge(data, idSelector, updateColumnNamesSelector, insertColumnNamesSelector);
102+
}
103+
}
104+
}

src/Microservices/Services.AuditLog/ClassifiedAds.Services.AuditLog/ClassifiedAds.Services.AuditLog.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>
Lines changed: 3 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,15 @@
11
using ClassifiedAds.CrossCuttingConcerns.OS;
22
using ClassifiedAds.Domain.Entities;
3-
using ClassifiedAds.Domain.Repositories;
4-
using Microsoft.EntityFrameworkCore;
5-
using System.Collections.Generic;
6-
using System.Linq;
7-
using System.Threading;
8-
using System.Threading.Tasks;
3+
using ClassifiedAds.Infrastructure.Persistence;
94

105
namespace ClassifiedAds.Services.AuditLog.Repositories
116
{
12-
public class Repository<T, TKey> : IRepository<T, TKey>
7+
public class Repository<T, TKey> : DbContextRepository<AuditLogDbContext, T, TKey>
138
where T : AggregateRoot<TKey>
149
{
15-
private readonly AuditLogDbContext _dbContext;
16-
private readonly IDateTimeProvider _dateTimeProvider;
17-
18-
protected DbSet<T> DbSet => _dbContext.Set<T>();
19-
20-
public IUnitOfWork UnitOfWork
21-
{
22-
get
23-
{
24-
return _dbContext;
25-
}
26-
}
27-
2810
public Repository(AuditLogDbContext dbContext, IDateTimeProvider dateTimeProvider)
11+
: base(dbContext, dateTimeProvider)
2912
{
30-
_dbContext = dbContext;
31-
_dateTimeProvider = dateTimeProvider;
32-
}
33-
34-
public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default)
35-
{
36-
if (entity.Id.Equals(default(TKey)))
37-
{
38-
entity.CreatedDateTime = _dateTimeProvider.OffsetNow;
39-
await DbSet.AddAsync(entity, cancellationToken);
40-
}
41-
else
42-
{
43-
entity.UpdatedDateTime = _dateTimeProvider.OffsetNow;
44-
}
45-
}
46-
47-
public void Delete(T entity)
48-
{
49-
DbSet.Remove(entity);
50-
}
51-
52-
public IQueryable<T> GetAll()
53-
{
54-
return _dbContext.Set<T>();
55-
}
56-
57-
public Task<T1> FirstOrDefaultAsync<T1>(IQueryable<T1> query)
58-
{
59-
return query.FirstOrDefaultAsync();
60-
}
61-
62-
public Task<T1> SingleOrDefaultAsync<T1>(IQueryable<T1> query)
63-
{
64-
return query.SingleOrDefaultAsync();
65-
}
66-
67-
public Task<List<T1>> ToListAsync<T1>(IQueryable<T1> query)
68-
{
69-
return query.ToListAsync();
7013
}
7114
}
7215
}
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22

3-
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
5-
<CodeAnalysisRuleSet>ClassifiedAds.ruleset</CodeAnalysisRuleSet>
6-
</PropertyGroup>
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<CodeAnalysisRuleSet>ClassifiedAds.ruleset</CodeAnalysisRuleSet>
6+
</PropertyGroup>
77

8-
<ItemGroup>
9-
<FrameworkReference Include="Microsoft.AspNetCore.App" />
10-
<PackageReference Include="ClosedXML" Version="0.95.4" />
11-
<PackageReference Include="EPPlus" Version="4.5.3.2" />
12-
<PackageReference Include="ExcelDataReader" Version="3.6.0" />
13-
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.0" />
14-
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
15-
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
16-
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0">
17-
<PrivateAssets>all</PrivateAssets>
18-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19-
</PackageReference>
20-
<PackageReference Include="Polly" Version="7.2.2" />
21-
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
22-
<PrivateAssets>all</PrivateAssets>
23-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
24-
</PackageReference>
25-
</ItemGroup>
8+
<ItemGroup>
9+
<FrameworkReference Include="Microsoft.AspNetCore.App" />
10+
<PackageReference Include="ClosedXML" Version="0.95.4" />
11+
<PackageReference Include="EPPlus" Version="4.5.3.2" />
12+
<PackageReference Include="ExcelDataReader" Version="3.6.0" />
13+
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.0" />
14+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
15+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
16+
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0">
17+
<PrivateAssets>all</PrivateAssets>
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
</PackageReference>
20+
<PackageReference Include="Polly" Version="7.2.2" />
21+
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
22+
<PrivateAssets>all</PrivateAssets>
23+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
24+
</PackageReference>
25+
</ItemGroup>
2626

27-
<ItemGroup>
28-
<ProjectReference Include="..\..\Common\ClassifiedAds.Application\ClassifiedAds.Application.csproj" />
29-
<ProjectReference Include="..\..\Common\ClassifiedAds.CrossCuttingConcerns\ClassifiedAds.CrossCuttingConcerns.csproj" />
30-
<ProjectReference Include="..\..\Common\ClassifiedAds.Domain\ClassifiedAds.Domain.csproj" />
31-
<ProjectReference Include="..\..\Common\ClassifiedAds.Infrastructure\ClassifiedAds.Infrastructure.csproj" />
32-
</ItemGroup>
27+
<ItemGroup>
28+
<ProjectReference Include="..\..\Common\ClassifiedAds.Application\ClassifiedAds.Application.csproj" />
29+
<ProjectReference Include="..\..\Common\ClassifiedAds.CrossCuttingConcerns\ClassifiedAds.CrossCuttingConcerns.csproj" />
30+
<ProjectReference Include="..\..\Common\ClassifiedAds.Domain\ClassifiedAds.Domain.csproj" />
31+
<ProjectReference Include="..\..\Common\ClassifiedAds.Infrastructure\ClassifiedAds.Infrastructure.csproj" />
32+
</ItemGroup>
3333

34-
<ItemGroup>
35-
<None Update="Certs\classifiedads.secretsencryption.pfx">
36-
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
37-
</None>
38-
</ItemGroup>
34+
<ItemGroup>
35+
<None Update="Certs\classifiedads.secretsencryption.pfx">
36+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
37+
</None>
38+
</ItemGroup>
3939

4040
</Project>
Lines changed: 4 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,15 @@
11
using ClassifiedAds.CrossCuttingConcerns.OS;
22
using ClassifiedAds.Domain.Entities;
3-
using ClassifiedAds.Domain.Repositories;
4-
using Microsoft.EntityFrameworkCore;
5-
using System.Collections.Generic;
6-
using System.Linq;
7-
using System.Threading;
8-
using System.Threading.Tasks;
3+
using ClassifiedAds.Infrastructure.Persistence;
94

105
namespace ClassifiedAds.Services.Configuration.Repositories
116
{
12-
public class Repository<T, TKey> : IRepository<T, TKey>
13-
where T : AggregateRoot<TKey>
7+
public class Repository<T, TKey> : DbContextRepository<ConfigurationDbContext, T, TKey>
8+
where T : AggregateRoot<TKey>
149
{
15-
private readonly ConfigurationDbContext _dbContext;
16-
private readonly IDateTimeProvider _dateTimeProvider;
17-
18-
protected DbSet<T> DbSet => _dbContext.Set<T>();
19-
20-
public IUnitOfWork UnitOfWork
21-
{
22-
get
23-
{
24-
return _dbContext;
25-
}
26-
}
27-
2810
public Repository(ConfigurationDbContext dbContext, IDateTimeProvider dateTimeProvider)
11+
: base(dbContext, dateTimeProvider)
2912
{
30-
_dbContext = dbContext;
31-
_dateTimeProvider = dateTimeProvider;
32-
}
33-
34-
public async Task AddOrUpdateAsync(T entity, CancellationToken cancellationToken = default)
35-
{
36-
if (entity.Id.Equals(default(TKey)))
37-
{
38-
entity.CreatedDateTime = _dateTimeProvider.OffsetNow;
39-
await DbSet.AddAsync(entity, cancellationToken);
40-
}
41-
else
42-
{
43-
entity.UpdatedDateTime = _dateTimeProvider.OffsetNow;
44-
}
45-
}
46-
47-
public void Delete(T entity)
48-
{
49-
DbSet.Remove(entity);
50-
}
51-
52-
public IQueryable<T> GetAll()
53-
{
54-
return _dbContext.Set<T>();
55-
}
56-
57-
public Task<T1> FirstOrDefaultAsync<T1>(IQueryable<T1> query)
58-
{
59-
return query.FirstOrDefaultAsync();
60-
}
61-
62-
public Task<T1> SingleOrDefaultAsync<T1>(IQueryable<T1> query)
63-
{
64-
return query.SingleOrDefaultAsync();
65-
}
66-
67-
public Task<List<T1>> ToListAsync<T1>(IQueryable<T1> query)
68-
{
69-
return query.ToListAsync();
7013
}
7114
}
7215
}

src/Microservices/Services.Identity/ClassifiedAds.Services.Identity/ClassifiedAds.Services.Identity.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>net6.0</TargetFramework>

0 commit comments

Comments
 (0)