Skip to content
This repository was archived by the owner on Apr 20, 2024. It is now read-only.

Commit 97b1830

Browse files
author
Morten Turn Pedersen
committed
Moved soft delete properties and functionality to new interface and class
1 parent b76ec87 commit 97b1830

File tree

6 files changed

+230
-83
lines changed

6 files changed

+230
-83
lines changed

NetCoreEntityFramework/Models/EntityBase.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,5 @@ public abstract class EntityBase
1515

1616
[Required]
1717
public DateTime Updated { get; set; }
18-
19-
public DateTime? DeletedAt { get; set; }
20-
21-
public bool Deleted { get; set; }
2218
}
2319
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
3+
namespace Nodes.NetCore.EntityFramework.Models
4+
{
5+
public abstract class EntitySoftDeleteBase : EntityBase
6+
{
7+
public DateTime? DeletedAt { get; set; }
8+
9+
public bool Deleted { get; set; }
10+
}
11+
}

NetCoreEntityFramework/Repositories/EntityRepository.cs

Lines changed: 13 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,21 @@ protected EntityRepository(DbContext context, DbSet<TEntity> table)
2121
Table = table;
2222
}
2323

24-
public async Task<TEntity> Get(Guid id, bool includeDeleted = false)
25-
{
26-
return await Table.FirstOrDefaultAsync(entity => (includeDeleted || !entity.Deleted) && entity.Id == id);
27-
}
24+
public virtual Task<TEntity> Get(Guid id) => Table.FirstOrDefaultAsync(entity => entity.Id == id);
2825

29-
public async Task<IEnumerable<TEntity>> GetList(
26+
public async virtual Task<IEnumerable<TEntity>> GetList(
3027
[Range(1, int.MaxValue)] int page,
3128
[Range(1, int.MaxValue)] int pageSize,
3229
Expression<Func<TEntity, bool>> where = null,
3330
Expression<Func<TEntity, object>> orderByExpression = null,
34-
OrderBy orderBy = OrderBy.Ascending,
35-
GetListMode mode = GetListMode.ExcludeDeleted)
31+
OrderBy orderBy = OrderBy.Ascending)
3632
{
3733
if (page < 1)
3834
throw new ArgumentException($"{nameof(page)} was below 1. Received: {page}", nameof(page));
3935
if(pageSize < 1)
4036
throw new ArgumentException($"{nameof(pageSize)} was below 1. Received: {pageSize}", nameof(pageSize));
4137

42-
IQueryable<TEntity> query = GetQueryable(where, orderByExpression, orderBy, mode);
38+
IQueryable<TEntity> query = GetQueryable(where, orderByExpression, orderBy);
4339

4440
// Pagination only skip if above page 1
4541
if (page > 1)
@@ -50,13 +46,12 @@ public async Task<IEnumerable<TEntity>> GetList(
5046
return await query.ToListAsync();
5147
}
5248

53-
public async Task<IEnumerable<TEntity>> GetList(
49+
public async virtual Task<IEnumerable<TEntity>> GetList(
5450
Expression<Func<TEntity, bool>> where = null,
5551
Expression<Func<TEntity, object>> orderByExpression = null,
56-
OrderBy orderBy = OrderBy.Ascending,
57-
GetListMode mode = GetListMode.ExcludeDeleted)
52+
OrderBy orderBy = OrderBy.Ascending)
5853
{
59-
IQueryable<TEntity> query = GetQueryable(where, orderByExpression, orderBy, mode);
54+
IQueryable<TEntity> query = GetQueryable(where, orderByExpression, orderBy);
6055

6156
return await query.ToListAsync();
6257
}
@@ -74,7 +69,7 @@ public virtual Task Add(TEntity entity)
7469
entity.Created = now;
7570
entity.Updated = now;
7671

77-
Context.Add(entity);
72+
Table.Add(entity);
7873

7974
return Task.CompletedTask;
8075
}
@@ -86,7 +81,7 @@ public virtual Task Update(TEntity entity)
8681

8782
entity.Updated = DateTime.UtcNow;
8883

89-
Context.Update(entity);
84+
Table.Update(entity);
9085

9186
return Task.CompletedTask;
9287
}
@@ -96,10 +91,7 @@ public virtual Task<bool> Delete(TEntity entity)
9691
if (entity == null)
9792
throw new ArgumentNullException(nameof(entity));
9893

99-
entity.DeletedAt = DateTime.UtcNow;
100-
entity.Deleted = true;
101-
102-
Context.Update(entity);
94+
Table.Remove(entity);
10395

10496
return Task.FromResult(true);
10597
}
@@ -117,45 +109,12 @@ public virtual async Task<bool> Delete(Guid id)
117109
return await Delete(entity);
118110
}
119111

120-
public virtual async Task<bool> Restore(Guid id)
121-
{
122-
if (id == Guid.Empty)
123-
throw new ArgumentException($"{nameof(id)} was not set", nameof(id));
124-
125-
TEntity entity = await Get(id, true);
126-
127-
if (entity == null)
128-
return false;
129-
130-
return await Restore(entity);
131-
}
132-
133-
public virtual Task<bool> Restore(TEntity entity)
134-
{
135-
if (entity == null)
136-
throw new ArgumentNullException(nameof(entity));
137-
138-
entity.Deleted = false;
139-
entity.DeletedAt = null;
140-
141-
Context.Update(entity);
142-
143-
return Task.FromResult(true);
144-
}
145-
146-
private IQueryable<TEntity> GetQueryable(
112+
protected IQueryable<TEntity> GetQueryable(
147113
Expression<Func<TEntity, bool>> where = null,
148114
Expression<Func<TEntity, object>> orderByExpression = null,
149-
OrderBy orderBy = OrderBy.Ascending,
150-
GetListMode mode = GetListMode.ExcludeDeleted)
115+
OrderBy orderBy = OrderBy.Ascending)
151116
{
152-
IQueryable<TEntity> query = mode switch
153-
{
154-
GetListMode.ExcludeDeleted => Table.Where(e => !e.Deleted),
155-
GetListMode.IncludeDeleted => Table,
156-
GetListMode.OnlyDeleted => Table.Where(e => e.Deleted),
157-
_ => throw new ArgumentException("Unknown setting", nameof(mode)),
158-
};
117+
IQueryable<TEntity> query = Table;
159118

160119
if (where != null)
161120
query = query.Where(where);
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using Nodes.NetCore.EntityFramework.Enums;
3+
using Nodes.NetCore.EntityFramework.Models;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.ComponentModel.DataAnnotations;
7+
using System.Linq;
8+
using System.Linq.Expressions;
9+
using System.Threading.Tasks;
10+
11+
namespace Nodes.NetCore.EntityFramework.Repositories
12+
{
13+
public abstract class EntitySoftDeleteRepository<TEntity> : EntityRepository<TEntity>, IEntitySoftDeleteRepository<TEntity> where TEntity : EntitySoftDeleteBase
14+
{
15+
protected EntitySoftDeleteRepository(DbContext context, DbSet<TEntity> table) : base(context, table)
16+
{
17+
}
18+
19+
public override Task<TEntity> Get(Guid id) => Get(id, false);
20+
21+
public Task<TEntity> Get(Guid id, bool includeDeleted = false) => Table.FirstOrDefaultAsync(entity => (includeDeleted || !entity.Deleted) && entity.Id == id);
22+
23+
public override Task<IEnumerable<TEntity>> GetList(
24+
[Range(1, int.MaxValue)] int page,
25+
[Range(1, int.MaxValue)] int pageSize,
26+
Expression<Func<TEntity, bool>> where = null,
27+
Expression<Func<TEntity, object>> orderByExpression = null,
28+
OrderBy orderBy = OrderBy.Ascending) => GetList(page, pageSize, where, orderByExpression, orderBy, GetListMode.ExcludeDeleted);
29+
30+
public override Task<IEnumerable<TEntity>> GetList(
31+
Expression<Func<TEntity, bool>> where = null,
32+
Expression<Func<TEntity, object>> orderByExpression = null,
33+
OrderBy orderBy = OrderBy.Ascending) => GetList(where, orderByExpression, orderBy, GetListMode.ExcludeDeleted);
34+
35+
public async virtual Task<IEnumerable<TEntity>> GetList(
36+
[Range(1, int.MaxValue)] int page,
37+
[Range(1, int.MaxValue)] int pageSize,
38+
Expression<Func<TEntity, bool>> where = null,
39+
Expression<Func<TEntity, object>> orderByExpression = null,
40+
OrderBy orderBy = OrderBy.Ascending,
41+
GetListMode mode = GetListMode.ExcludeDeleted)
42+
{
43+
if (page < 1)
44+
throw new ArgumentException($"{nameof(page)} was below 1. Received: {page}", nameof(page));
45+
if (pageSize < 1)
46+
throw new ArgumentException($"{nameof(pageSize)} was below 1. Received: {pageSize}", nameof(pageSize));
47+
48+
IQueryable<TEntity> query = GetQueryable(where, orderByExpression, orderBy, mode);
49+
50+
// Pagination only skip if above page 1
51+
if (page > 1)
52+
query = query.Skip((page - 1) * pageSize);
53+
54+
query = query.Take(pageSize);
55+
56+
return await query.ToListAsync();
57+
}
58+
59+
public async virtual Task<IEnumerable<TEntity>> GetList(
60+
Expression<Func<TEntity, bool>> where = null,
61+
Expression<Func<TEntity, object>> orderByExpression = null,
62+
OrderBy orderBy = OrderBy.Ascending,
63+
GetListMode mode = GetListMode.ExcludeDeleted)
64+
{
65+
IQueryable<TEntity> query = GetQueryable(where, orderByExpression, orderBy, mode);
66+
67+
return await query.ToListAsync();
68+
}
69+
70+
public override Task<bool> Delete(TEntity entity)
71+
{
72+
if (entity == null)
73+
throw new ArgumentNullException(nameof(entity));
74+
75+
entity.DeletedAt = DateTime.UtcNow;
76+
entity.Deleted = true;
77+
78+
Table.Update(entity);
79+
80+
return Task.FromResult(true);
81+
}
82+
83+
public virtual async Task<bool> Restore(Guid id)
84+
{
85+
if (id == Guid.Empty)
86+
throw new ArgumentException($"{nameof(id)} was not set", nameof(id));
87+
88+
TEntity entity = await Get(id, true);
89+
90+
if (entity == null)
91+
return false;
92+
93+
return await Restore(entity);
94+
}
95+
96+
public virtual Task<bool> Restore(TEntity entity)
97+
{
98+
if (entity == null)
99+
throw new ArgumentNullException(nameof(entity));
100+
101+
entity.Deleted = false;
102+
entity.DeletedAt = null;
103+
104+
Table.Update(entity);
105+
106+
return Task.FromResult(true);
107+
}
108+
109+
protected IQueryable<TEntity> GetQueryable(
110+
Expression<Func<TEntity, bool>> where = null,
111+
Expression<Func<TEntity, object>> orderByExpression = null,
112+
OrderBy orderBy = OrderBy.Ascending,
113+
GetListMode mode = GetListMode.ExcludeDeleted)
114+
{
115+
var query = GetQueryable(where, orderByExpression, orderBy);
116+
117+
switch(mode)
118+
{
119+
case GetListMode.ExcludeDeleted:
120+
query = query.Where(e => !e.Deleted);
121+
break;
122+
case GetListMode.OnlyDeleted:
123+
query = query.Where(e => e.Deleted);
124+
break;
125+
//Do nothing if everything should be included
126+
case GetListMode.IncludeDeleted:
127+
break;
128+
default:
129+
throw new ArgumentException("Unknown setting", nameof(mode));
130+
}
131+
132+
return query;
133+
}
134+
}
135+
}

NetCoreEntityFramework/Repositories/IEntityRepository.cs

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using Microsoft.EntityFrameworkCore;
2-
using Nodes.NetCore.EntityFramework.Enums;
1+
using Nodes.NetCore.EntityFramework.Enums;
32
using Nodes.NetCore.EntityFramework.Models;
43
using System;
54
using System.Collections.Generic;
@@ -15,8 +14,7 @@ public interface IEntityRepository<TEntity> : IAsyncDisposable where TEntity : E
1514
/// Get the entity with the given <paramref name="id"/>.
1615
/// </summary>
1716
/// <param name="id">The ID of the entity to fetch.</param>
18-
/// <param name="includeDeleted">If true, also search amongst the soft deleted entities.</param>
19-
Task<TEntity> Get(Guid id, bool includeDeleted = false);
17+
Task<TEntity> Get(Guid id);
2018

2119
/// <summary>
2220
/// Get multiple entities paginated.
@@ -26,29 +24,25 @@ public interface IEntityRepository<TEntity> : IAsyncDisposable where TEntity : E
2624
/// <param name="where">The filter expression.</param>
2725
/// <param name="orderByExpression">The expression to order by.</param>
2826
/// <param name="orderBy">To order by ascending or descending.</param>
29-
/// <param name="mode">Whether to include deleted or not.</param>
3027
/// <exception cref="ArgumentException"></exception>
3128
Task<IEnumerable<TEntity>> GetList(
3229
[Range(1, int.MaxValue)] int page,
3330
[Range(1, int.MaxValue)] int pageSize,
3431
Expression<Func<TEntity, bool>> where = null,
3532
Expression<Func<TEntity, object>> orderByExpression = null,
36-
OrderBy orderBy = OrderBy.Ascending,
37-
GetListMode mode = GetListMode.ExcludeDeleted);
33+
OrderBy orderBy = OrderBy.Ascending);
3834

3935
/// <summary>
4036
/// Get multiple entities.
4137
/// </summary>
4238
/// <param name="where">The filter expression.</param>
4339
/// <param name="orderByExpression">The expression to order by.</param>
4440
/// <param name="orderBy">To order by ascending or descending.</param>
45-
/// <param name="mode">Whether to include deleted or not.</param>
4641
/// <exception cref="ArgumentException"></exception>
4742
Task<IEnumerable<TEntity>> GetList(
4843
Expression<Func<TEntity, bool>> where = null,
4944
Expression<Func<TEntity, object>> orderByExpression = null,
50-
OrderBy orderBy = OrderBy.Ascending,
51-
GetListMode mode = GetListMode.ExcludeDeleted);
45+
OrderBy orderBy = OrderBy.Ascending);
5246

5347
/// <summary>
5448
/// Add the given <paramref name="entity"/> to the database.
@@ -73,24 +67,10 @@ Task<IEnumerable<TEntity>> GetList(
7367
Task<bool> Delete(TEntity entity);
7468

7569
/// <summary>
76-
/// Soft the delete the entity with the given <paramref name="id"/>.
70+
/// Delete the entity with the given <paramref name="id"/>.
7771
/// </summary>
7872
/// <param name="id">The ID of the entity to soft delete.</param>
7973
/// <exception cref="ArgumentException"></exception>
8074
Task<bool> Delete(Guid id);
81-
82-
/// <summary>
83-
/// Restore/undelete the entity with the given <paramref name="id"/>.
84-
/// </summary>
85-
/// <param name="id">The ID of the entity to restore.</param>
86-
/// <exception cref="ArgumentException"></exception>
87-
Task<bool> Restore(Guid id);
88-
89-
/// <summary>
90-
/// Restore/undelete the given <paramref name="entity"/>.
91-
/// </summary>
92-
/// <param name="entity">The entity to restore.</param>
93-
/// <exception cref="ArgumentNullException"></exception>
94-
Task<bool> Restore(TEntity entity);
9575
}
9676
}

0 commit comments

Comments
 (0)