I'm developing a web application using .NET 8 and Clean Architecture.
There I'm trying to implement a generic repository that includes two methods for the bulk-update and bulk-delete
that use EF Core 8's ExecuteUpdate() and ExecuteDelete() methods, so that I can update/delete the database without being forced to select the entries that must be deleted in advance.
MyRepository.cs (located in the Infrastructure Layer)
public class MyRepository<TEntity> : IMyRepository<TEntity> where TEntity : class, IBaseEntity, new()
{
protected readonly IMyDataContext DataContext;
protected MyRepository(IMyDataContext dataContext)
{
DataContext = dataContext;
}
// src: https://stackoverflow.com/a/75799111/5757823
public int BulkUpdate(Expression<Func<TEntity, bool>> query, Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> expression)
{
return context.Set<TEntity>().Where(query).ExecuteUpdate(expression);
}
public int BulkDelete(Expression<Func<TEntity, bool>> query)
{
return this.context.Set<TEntity>().Where(query).ExecuteDelete();
}
}
The code sample above needs to include the Microsoft.EntityFrameworkCore.Query namespace to use the SetPropertyCalls class in the BulkUpdate()method.
In my understanding, the according interface IMyRepository must be located in the Application Layer
since it's going to be used from most of my Application Services.
IMyRepository.cs (located in the Application Layer)
public interface IMyRepository<TEntity> where TEntity : class, IBaseEntity, new()
{
int BulkUpdate(Expression<Func<TEntity, bool>> query, Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> expression);
int BulkDelete(Expression<Func<TEntity, bool>> query);
}
To achieve this, I would have to include the Microsoft.EntityFrameworkCore.Query namespace also in the interface.
But in my understanding, the Application Layer should be technology-agnostic, i.e. it's not allowed to include Microsoft.EntityFrameworkCore there.
How can I obtain a generic repository that uses EF Core 8's ExecuteUpdate() and ExecuteDelete()methods while keeping the application layer (and the interface) agnostic from EF Core?
This is solution for replacing types in expression. I hope it is universal solution and can be used not just for replacing types for
SetPropertyCallsUsage in your repository:
Introduce interfaces for mimic EF Core classes:
Introduce
RepositoryUtils:And core of this solution
ExpressionTypeMapper:As I said in comments, generic repository pattern is anti-pattern for EF Core. Do not introduce thing that will slowdown your development and increase project complexity.
ExpressionTypeMapperis a result of many years of experience and can be challenging for others to support.