-
Notifications
You must be signed in to change notification settings - Fork 0
/
BaseRepository.cs
104 lines (84 loc) · 4.06 KB
/
BaseRepository.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using BenjaminAbt.EntityFrameworkDemo.Database.Entities;
using LinqKit;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace BenjaminAbt.EntityFrameworkDemo.Database.Repositories;
// This is the basis of my generic, DB server neutral EF Core repository - with a few special features
public abstract class BaseRepository<T> : IBaseRepository<T> where T : BaseEntity
{
protected IBaseDbContext DbContext { get; }
private readonly DbSet<T> _set;
private readonly IQueryable<T> _expandableSet;
// Unlike other examples of generic repositories, at this point I want not only the context, but also the DbSet.
// This lowers the overhead and helps me access the set
// more easily to take advantage of special features like Expandable.
protected BaseRepository(IBaseDbContext dbContext, DbSet<T> entitySet)
{
DbContext = dbContext;
_set = entitySet;
// AsExpandable is a feature of LinqKit that allows us to define our
// own Expression Profiles to create projections in a central location; similar
// to what we know from AutoMapper Projections - only better.
// Why better, see Profile Sample.
_expandableSet = entitySet.AsExpandable();
}
// I override all standard crud methods to allow generic access
///<summary>
///The method adds an entity to the database.
///</summary>
///<param name="entity"> The entity to be added to the database. </param>
///<returns> EntityEntry instance corresponding to the entity. </returns>
public EntityEntry<T> Add(T entity)
=> _set.Add(entity);
///<summary>
///Adds a range of entities to the database.
///</summary>
///<param name="entities"> The entities to be added to the database </param>
public void AddRange(IEnumerable<T> entities)
=> _set.AddRange(entities);
///<summary>
///Attaches the entity to the database.
///</summary>
///<param name="entity"> The entity to be attached. </param>
///<returns> EntityEntry instance corresponding to the entity. </returns>
public EntityEntry<T> Attach(T entity)
=> _set.Attach(entity);
///<summary>
///Deletes entity from the database.
///</summary>
///<param name="entity"> The entity to be deleted. </param>
///<returns> EntityEntry instance corresponding to the entity. </returns>
public EntityEntry<T> Delete(T entity)
=> _set.Remove(entity);
/// <summary>
/// Deletes a range of entities from the database.
/// </summary>
/// <param name="entities">The entities to delete.</param>
/// <returns>A list of deleted entities.</returns>
public List<EntityEntry<T>> Delete(IEnumerable<T> entities)
=> entities.Select(Delete).ToList();
///<summary>
///The method returns an IQueryable of T for a given database tracking option.
///</summary>
///<param name="to"> The database tracking option. </param>
///<returns> IQueryable instance of T type. </returns>
public IQueryable<T> Query(DbTrackingOptions to)
=> _expandableSet.With(to);
// The SaveChanges methods are also provided, but the return is
// a typed struct rather than a non-saying Int
///<summary>
///Saves changes to the database using a cancellation token.
///</summary>
///<param name="ct"> Cancellation token. </param>
///<returns> An instance of DbSaveChangesResult. </returns>
public ValueTask<DbSaveChangesResult> SaveChangesAsync(CancellationToken ct)
=> DbContext.SaveChangesAsync(ct);
///<summary>
///Saves changes to the database with an option to update change state.
///</summary>
///<param name="updateChangeTrackerStates"> Boolean indicator to update change tracker states. </param>
///<param name="ct"> Cancellation token. </param>
///<returns> An instance of DbSaveChangesResult. </returns>
public ValueTask<DbSaveChangesResult> SaveChangesAsync(bool updateChangeTrackerStates, CancellationToken ct)
=> DbContext.SaveChangesAsync(updateChangeTrackerStates, ct);
}