EasyCore.EFCoreRepository
8.0.4
See the version list below for details.
dotnet add package EasyCore.EFCoreRepository --version 8.0.4
NuGet\Install-Package EasyCore.EFCoreRepository -Version 8.0.4
<PackageReference Include="EasyCore.EFCoreRepository" Version="8.0.4" />
<PackageVersion Include="EasyCore.EFCoreRepository" Version="8.0.4" />
<PackageReference Include="EasyCore.EFCoreRepository" />
paket add EasyCore.EFCoreRepository --version 8.0.4
#r "nuget: EasyCore.EFCoreRepository, 8.0.4"
#:package EasyCore.EFCoreRepository@8.0.4
#addin nuget:?package=EasyCore.EFCoreRepository&version=8.0.4
#tool nuget:?package=EasyCore.EFCoreRepository&version=8.0.4
ποΈ EasyCore.EFCoreRepository
δΈζ README | MongoDb δΈζ README
π Overview Repository is a crucial concept in software development, widely used especially in Domain-Driven Design (DDD) π― and the Data Access Layer. Repository is a design pattern ποΈ that abstracts the data access layer, encapsulating data access logic and decoupling upper-level business logic from underlying data storage. Repository acts like an interface π¦ to the data warehouse, managing persistence operations (CRUD) for entity objects.
π Quick Start
1. π Program Registration
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.EasyCoreDependencie();
builder.Services.AddDbContext<TestDbContext>();
// β¨ Use EasyCore EFCore Repository
builder.Services.EasyCoreEFCoreRepository();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
2. π·οΈ Entity Inheritance
EasyCore.EFCoreRepository provides a feature-rich entity base class EasyCoreEntity, including:
π Concurrency Token
ποΈ Soft Delete
π’ Multi-Tenant ID
// π‘ Note: The generic type in `EasyCoreEntity<TKey>` is the primary key type of the table
public class TestEntity : EasyCoreEntity<Guid>
{
public string Name { get; set; }
public int Age { get; set; }
}
3. π§ Repository Class Inheritance
EasyCore.EFCoreRepository provides complete repository abstraction and implementation:
Repository Interface π
public interface ITestEntityRepository : IRepository<TestDbContext, TestEntity>, ITransientDependencie
{
// π‘ ITransientDependencie is the auto-injection marker from EasyCore.Dependencie
}
Repository Implementation βοΈ
public class TestEntityRepository : EfCoreRepository<TestDbContext, TestEntity>, ITestEntityRepository
{
public TestEntityRepository(TestDbContext dbContext, IServiceProvider serviceProvider)
: base(dbContext, serviceProvider)
{
}
}
4.π‘ Using the Repository
4.1 π― Basic CRUD Operations
[Route("api/[controller]")]
[ApiController]
public class RepositoryController : ControllerBase
{
private readonly ITestEntityRepository _repository;
public RepositoryController(ITestEntityRepository repository) => _repository = repository;
// π Query
[HttpGet]
public async Task<TestEntity> Get()
{
return await _repository.GetAsync(e => e.Name == "Test");
}
// β Insert
[HttpPost]
public async Task Post()
{
await _repository.InsertAsync(new TestEntity {
Name = "Test",
Age = 10,
Id = Guid.NewGuid()
}, true);
}
// βοΈ Update
[HttpPut]
public async Task Put()
{
var entity = await _repository.GetAsync(e => e.Name == "Test");
entity.Age = 20;
await _repository.UpdateAsync(entity, true);
}
// ποΈ Delete (Soft Delete)
[HttpDelete]
public async Task Delete()
{
var entity = await _repository.GetAsync(e => e.Age == 20);
entity.IsDeleted = true;
await _repository.UpdateAsync(entity, true);
}
}
4.2 π Complete API List
EasyCore.EFCoreRepository provides a rich set of API methods:
π§ Filter Management
EfCoreRepository<TDbContext, TEntity> AddFilter(Type filterType);
EfCoreRepository<TDbContext, TEntity> RemoveFilter(Type filterType);
β Insert Operations
Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
TEntity Insert(TEntity entity, bool autoSave = false);
Task InsertManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default);
void InsertMany(IEnumerable<TEntity> entities, bool autoSave = false);
βοΈ Update Operations
Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
TEntity Update(TEntity entity, bool autoSave = false);
Task UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default);
void UpdateMany(IEnumerable<TEntity> entities, bool autoSave = false);
ποΈ Delete Operations
Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default);
void Delete(TEntity entity, bool autoSave = false);
Task DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default);
void DeleteMany(IEnumerable<TEntity> entities, bool autoSave = false);
πΎ Save Operations
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
int SaveChanges();
π Query Operations
// Get List
Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default);
List<TEntity> GetList(bool includeDetails = false);
// Count
Task<long> GetCountAsync(CancellationToken cancellationToken = default);
long GetCount();
Task<long> GetCountAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
long GetCount(Expression<Func<TEntity, bool>> predicate);
// Paged Query
Task<List<TEntity>> GetPagedListAsync(int skipCount, int maxResultCount, string? sorting = null, bool includeDetails = false, CancellationToken cancellationToken = default);
List<TEntity> GetPagedList(int skipCount, int maxResultCount, string? sorting = null, bool includeDetails = false);
// Conditional Query
Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default);
List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false);
// Single Entity Query
Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false, CancellationToken cancellationToken = default);
TEntity? Get(Expression<Func<TEntity, bool>> predicate, bool includeDetails = false);
β‘ Direct Delete Operations
Task DeleteDirectAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
void DeleteDirect(Expression<Func<TEntity, bool>> predicate);
void DeleteManyDirect(IEnumerable<TEntity> entities, bool autoSave = false);
Task DeleteManyDirectAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default);
5.ποΈ Advanced Features
π― WhereIf Support
EasyCore.EFCoreRepository provides intelligent conditional query support:
IQueryable<T>.WhereIf(xxx != null, x => x.xxx == xxx)
β¨ Feature: The subsequent filter condition is only executed when the xxx != null condition is met; otherwise, the code continues execution.
6. π Data Filters
EasyCore.EFCoreRepository includes two practical built-in data filters:
ποΈ ISoftDeleteFilter - Soft Delete Filter
π’ ITenantFilter - Tenant Filter
Custom Filter Example π¨:
public class CustomDataFilter : IDataFilter, ITransientDependencie
{
public IQueryable<TEntity> Apply<TEntity>(IQueryable<TEntity> query) where TEntity : class, IEntity
{
query = query.Where(e => ((e as TestEntity)!.Name == "Test"));
return query;
}
}
Dynamic Filter Management β‘:
_repository
.RemoveFilter(typeof(ITenantFilter)) // ποΈ Remove Tenant Filter
.RemoveFilter(typeof(ISoftDeleteFilter)) // ποΈ Remove Soft Delete Filter
.AddFilter(typeof(CustomDataFilter)) // β Add Custom Filter
.Delete(e => e.Name == "Test1", true); // π― Execute Operation
π EasyCore.UnitOfWork
π― Unit of Work Pattern
EasyCore.UnitOfWork provides the SaveChangesAttribute feature, making data persistence simple and efficient! β¨
1. π Program Registration
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.EasyCoreDependencie();
builder.Services.AddDbContext<TestDbContext>();
// β¨ Use EasyCore EFCore Repository
builder.Services.EasyCoreEFCoreRepository();
// π Use EasyCore UnitOfWork
builder.Services.EasyCoreUnitOfWork();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
}
}
2. π Abstract Interface Definition
public interface IUnitOfWorkTest : ITransientDependencie
{
/// <summary>
/// π― Test Entity Unit of Work
/// </summary>
Task<TestEntity> EntityUnitOfWork();
/// <summary>
/// π° Test Transaction Unit of Work
/// </summary>
Task<TestEntity> Transaction();
}
public interface IUnitOfWorkTest2 : ITransientDependencie
{
/// <summary>
/// π― Test Entity Unit of Work
/// </summary>
Task<TestEntity> EntityUnitOfWork();
}
3. π·οΈ Using the SaveChangesAttribute
Method Level Usage π―:
public class UnitOfWorkTest : IUnitOfWorkTest
{
private readonly ITestEntityRepository _repository;
public UnitOfWorkTest(ITestEntityRepository repository) => _repository = repository;
[SaveChanges(typeof(TestDbContext))]
public Task<TestEntity> EntityUnitOfWork()
=> _repository.InsertAsync(new TestEntity { Name = "Test", Age = 10, Id = Guid.NewGuid() });
[SaveChanges(true, typeof(TestDbContext))] // π° Enable Transaction
public Task<TestEntity> Transaction()
=> _repository.InsertAsync(new TestEntity { Name = "Test", Age = 10, Id = Guid.NewGuid() });
}
Class Level Usage ποΈ:
[SaveChanges(typeof(TestDbContext))]
public class UnitOfWorkTest2 : IUnitOfWorkTest2
{
private readonly ITestEntityRepository _repository;
public UnitOfWorkTest2(ITestEntityRepository repository) => _repository = repository;
public Task<TestEntity> EntityUnitOfWork()
=> _repository.InsertAsync(new TestEntity { Name = "Test", Age = 10, Id = Guid.NewGuid() });
}
π‘ Attribute Parameter Description:
First parameter: Whether it is a database transaction; when true, performs a transactional save π°
Second parameter: Specifies the database DbContext object to save
π EasyCore.EntityChange
π Entity Change Tracking
EasyCore.EFCoreEntityChange provides powerful entity change tracking capabilities! π΅οΈ
1. π Program Registration
builder.Services.AddDbContext<TestDbContext>(op =>
{
op.UseEasyCoreEntityChange(builder.Services); // β¨ Use EasyCore EFCore Entity Change Tracking
});
builder.Services.AddDbContext<Test2DbContext>(op =>
{
op.UseEasyCoreEntityChange(builder.Services); // β¨ Use EasyCore EFCore Entity Change Tracking
});
// π§ Enable EasyCore Entity Change Service
builder.Services.EasyCoreEntityChange();
2. π― Using Entity Change Tracking
public class EntityChange :
IEntityUpdatedChangeHandler<TestEntity>,
IEntityDeletedChangeHandler<TestEntity>,
IEntityAddedChangeHandler<TestEntity>
{
private readonly ILogger<EntityChange> _logger;
public EntityChange(ILogger<EntityChange> logger) => _logger = logger;
// β Entity Added Handler
public async Task OnAddedAsync(TestEntity entity)
{
_logger.LogInformation($"π Entity Added: Id:{entity.Id}; Name:{entity.Name}; Age:{entity.Age};");
await Task.CompletedTask;
}
// ποΈ Entity Deleted Handler
public async Task OnDeletedAsync(TestEntity entity)
{
_logger.LogInformation($"ποΈ Entity Deleted: Id:{entity.Id}; Name:{entity.Name}; Age:{entity.Age};");
await Task.CompletedTask;
}
// βοΈ Entity Updated Handler
public Task OnUpdatedAsync(TestEntity oldEntity, TestEntity currentEntity)
{
_logger.LogInformation($"βοΈ Entity Updated: " +
$"Id:{oldEntity.Id} β {currentEntity.Id}; " +
$"Name:{oldEntity.Name} β {currentEntity.Name}; " +
$"Age:{oldEntity.Age} β {currentEntity.Age};");
return Task.CompletedTask;
}
}
π― Supported Change Interfaces:
IEntityAddedChangeHandler<TEntity> - Entity Added Handler β
IEntityDeletedChangeHandler<TEntity> - Entity Deleted Handler ποΈ
IEntityUpdatedChangeHandler<TEntity> - Entity Updated Handler βοΈ
π Custom Entity And Custom Data Filter
1. User-Defined Database Entityπ¦
Users can configure custom user entities based on their specific project requirements.
public class CustomEntity : EasyCoreEntity<Guid>
{
public string CreateId{ get; set; }
}
public class TestCustomEntity : CustomEntity
{
}
The CustomEntity represents a user-defined entity object. This custom entity contains a CreateId field. During the save operation, the IEntityAddedChangeHandler<TEntity> interface can be utilized to automatically save the current user's ID.
public class TestCustomEntityRepository : EfCoreRepository<TestDbContext, TestCustomEntity>,ITestCustomEntityRepository,IEntityAddedChangeHandler<TestCustomEntity>
{
public TestCustomEntityRepository(TestDbContext dbContext, IServiceProvider serviceProvider) : base(dbContext, serviceProvider)
{
}
public async Task OnAddedAsync(TestCustomEntity entity)
{
if (entity is CustomEntity customEntity)
{
customEntity.CreateId = "Test";
}
await Task.CompletedTask;
}
}
2. User-defined Data Filtersπ
Users can configure custom data filters based on their specific project requirements.
public class TestEntityRepository :
EfCoreRepository<TestDbContext, TestEntity>,
ITestEntityRepository
{
public TestEntityRepository(TestDbContext dbContext, IServiceProvider serviceProvider) : base(dbContext, serviceProvider)
{
}
/// <summary>
/// Applies permanent data filters before persisting entities (Insert/Update/Delete).
/// This method is called during the persistence pipeline to enforce global filters.
/// </summary>
/// <param name="dataFilters">The list of data filters that are currently scheduled for execution.</param>
/// <returns>The updated list of data filters after applying permanent filter rules.</returns>
public override List<IDataFilter> OnApplyPersistingFilters(List<IDataFilter> dataFilters)
{
AddOnce(dataFilters, typeof(CustomDataFilter));
RemoveIfExistsFilter(dataFilters, typeof(CustomDataFilter));
return dataFilters;
}
}
Override the OnApplyPersistingFilters method to add or modify persistent filter settings.
β¨ Feature: When entity add, delete, or update operations are completed, the system automatically calls the corresponding interface methods, enabling seamless change tracking!
π Summary
The EasyCore.EFCoreRepository series of components provides:
ποΈ Complete Repository Pattern Implementation
π Smart Unit of Work Management
π Powerful Entity Change Tracking
π― Rich Querying and Filtering Capabilities
β‘ High-Performance Data Access
Making your data access layer more elegant, powerful, and maintainable! β¨
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.AspNetCore.Mvc (>= 2.1.3)
- Microsoft.EntityFrameworkCore (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.