Provides generic repository base classes for implementing the Repository and Unit of Work patterns with Entity Framework Core.
$ dotnet add package RA.Utilities.Data.EntityFrameworkProvides generic base classes for implementing the Repository and Unit of Work patterns with Entity Framework Core.
This package is the concrete implementation layer for the abstractions defined in RA.Utilities.Data.Abstractions.
This library accelerates the setup of a data access layer by providing ready-to-use, generic base classes that handle common data operations. By using these implementations, you can:
RepositoryBase, ReadRepositoryBase, or WriteRepositoryBase to get a full suite of data access methods out of the box.UnitOfWork implementation to manage database transactions and ensure that changes are saved atomically.RA.Utilities.Data.Abstractions.Install the package via the .NET CLI:
dotnet add package RA.Utilities.Data.EntityFramework
Or through the NuGet Package Manager console:
Install-Package RA.Utilities.Data.EntityFramework
This package includes extension methods to simplify service registration for the generic repository patterns.
Provides extension methods for setting up dependency injection for data-related services.
Namespace: RA.Utilities.Extensions
Source: Extensions/DependencyInjectionExtensions.cs
public static class DependencyInjectionExtensions
Adds the generic IRepositoryBase<> and its implementation RepositoryBase<> to the service collection as a scoped service. This allows you to inject IRepositoryBase<T> directly for any entity without creating a specific repository class.
Definition
public static IServiceCollection AddRepositoryBase(this IServiceCollection services)
// In Program.cs
builder.Services.AddRepositoryBase();
// Now you can inject IRepositoryBase in your services
public class MyService(IRepositoryBase productRepository)
{
// ... use productRepository
}
Adds the generic IReadRepositoryBase<> and its implementation ReadRepositoryBase<> as a scoped service.
Use this if you only need read operations for certain entities, adhering to the Command Query Separation (CQS) principle.
Definition
public static IServiceCollection AddReadRepositoryBase(this IServiceCollection services)
Adds the generic IWriteRepositoryBase<> and its implementation WriteRepositoryBase<> as a scoped service.
Use this if you only need write operations for certain entities.
[!NOTE]
The WriteRepositoryBase also contains the SaveChangesAsync method. In a Unit of Work pattern, saving changes is typically controlled by the UnitOfWork class, not individual repositories, to ensure transactional integrity.
Definition
public static IServiceCollection AddWriteRepositoryBase(this IServiceCollection services)
Here’s a step-by-step guide to setting up a data access layer using this package.
Create your Entity Framework DbContext and make sure it implements IDbContext from RA.Utilities.Data.Abstractions.
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Product> Products { get; set; }
// Other DbSets...
}
Create your own repository interfaces and classes. The interfaces should inherit from IRepository<TEntity> (from RA.Utilities.Data.Abstractions) and the classes should inherit from Repository<TEntity>.
// In your Application/Domain layer (referencing RA.Utilities.Data.Abstractions)
public interface IProductRepository : IRepositoryBase<Product>
{
Task<IEnumerable<Product>> GetTopSellingProductsAsync(int count);
}
// In your Infrastructure/Data layer (referencing this package)
public class ProductRepository : RepositoryBase<Product>, IProductRepository
{
public ProductRepository(ApplicationDbContext context) : base(context)
{
}
public async Task<IEnumerable<Product>> GetTopSellingProductsAsync(int count)
{
// Custom data access logic
return await _dbSet.OrderByDescending(p => p.UnitsSold).Take(count).ToListAsync();
}
}
In your Program.cs or Startup.cs, register the DbContext, the UnitOfWork, and your custom repositories.
using RA.Utilities.Data.Abstractions;
using RA.Utilities.Data.EntityFramework;
// ...
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// Register UnitOfWork and Repositories
builder.Services.AddScoped<IUnitOfWork, UnitOfWork<ApplicationDbContext>>();
builder.Services.AddScoped<IProductRepository, ProductRepository>();
Inject IUnitOfWork into your services or controllers to access repositories and save changes.
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IUnitOfWork _unitOfWork;
public ProductsController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
[HttpGet]
public async Task<IActionResult> GetTopProducts()
{
var productRepository = _unitOfWork.GetRepository<IProductRepository>();
var products = await productRepository.GetTopSellingProductsAsync(5);
return Ok(products);
}
[HttpPost]
public async Task<IActionResult> CreateProduct(Product product)
{
var productRepository = _unitOfWork.GetRepository<IProductRepository>();
await productRepository.AddAsync(product);
await _unitOfWork.SaveChangesAsync(); // Commits the transaction
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
}
RA.Utilities.Data.Abstractions: Provides the core interfaces (IRepository<T>, IUnitOfWork, etc.) that this package implements.Microsoft.EntityFrameworkCore: The underlying ORM used for the implementations.For more information on how this package fits into the larger RA.Utilities ecosystem, please see the officiary documentation.
If you have suggestions or find a bug, please open an issue in the RA.Utilities GitHub repository. Contributions are welcome!