20
DecImplementing Repository Pattern in ASP.NET Core
Repository Pattern in ASP.NET Core
In software development, managing data access can become complex quickly. One way to simplify and organize this aspect of your application is to use the Repository Pattern. This design helps manage and maintain data access.
In this ASP.NET Core Tutorial, we will talk about the Repository Pattern in ASP.NET Core, its functioning, and its importance. If in case you need more detailed information about other ASP.NET-related topics, mddake sure you have enrolled in our ASP.NET Core Certification Training.
What is a Repository Pattern?
The Repository Pattern is a design, that acts like a middleman between the application and data source. The main aim is to have a cleaner code that is easy to maintain and reuse both logic and data access.
Repository Pattern Interface
To implement the Repository Pattern, we first define an interface that outlines the methods for accessing data. This interface will represent the contract that any repository class must fulfill. A simple example is shown below:
public interface IRepository<T>
{
IEnumerable<T> GetAll();
T GetById(int id);
void Add(T entity);
void Update(T entity);
void Delete(int id);
}
Any repository class must carry out the basic CRUD operations (Create, Read, Update, Delete) defined by this interface.
Read More: ASP.NET Core And Entity Framework Core CRUD Operations |
Core Principles of the Repository Pattern
- Abstraction- Separates the data access logic from the business logic.
- Encapsulation-Encapsulates the logic required to access data sources.
- Testability-Makes unit testing easier by allowing you to mock data access layers.
- DRY (Don't Repeat Yourself)-Reduces code duplication by centralizing data access logic.
Repository Pattern - SQL Server Implementation
1.) Creating Models
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
2.) Context Class and the Database Connection
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions options) : base(options) { }
public DbSet Products { get; set; }
}
3.) Repository Pattern Logic
public class Repository<T> : IRepository<T> where T : class
{
private readonly ApplicationDbContext _context;
private readonly DbSet<T> _dbSet;
public Repository(ApplicationDbContext context)
{
_context = context;
_dbSet = _context.Set<T>();
}
public IEnumerable<T> GetAll()
{
return _dbSet.ToList();
}
public T GetById(int id)
{
return _dbSet.Find(id);
}
public void Add(T entity)
{
_dbSet.Add(entity);
_context.SaveChanges();
}
public void Update(T entity)
{
_dbSet.Attach(entity);
_context.Entry(entity).State = EntityState.Modified;
_context.SaveChanges();
}
public void Delete(int id)
{
var entity = _dbSet.Find(id);
_dbSet.Remove(entity);
_context.SaveChanges();
}
}
4.) Repository User Classes
public class ProductsController : Controller
{
private readonly IRepository<Product> _productRepository;
public ProductsController(IRepository<Product> productRepository)
{
_productRepository = productRepository;
}
public IActionResult Index()
{
var products = _productRepository.GetAll();
return View(products);
}
// Other action methods for Create, Edit, Delete, etc.
}
5.) Creating a Repository Wrapper
public interface IRepositoryWrapper
{
IRepository<Product> Product { get; }
// Add other repositories here
void Save();
}
public class RepositoryWrapper : IRepositoryWrapper
{
private readonly ApplicationDbContext _context;
private IRepository<Product> _productRepository;
public RepositoryWrapper(ApplicationDbContext context)
{
_context = context;
}
public IRepository<Product> Product
{
get
{
if (_productRepository == null)
{
_productRepository = new Repository<Product>(_context);
}
return _productRepository;
}
}
public void Save()
{
_context.SaveChanges();
}
}
Benefits of Repository Pattern
- Code Reusability- By centralizing data access logic, you can reuse the same repository methods across different parts of your application.
- Ease of Testing—The abstraction allows you to mock the data layer easily, making unit tests more straightforward and reliable.
- Separation of Concerns- By keeping the data access logic separate from the business logic, the codebase is cleaner and more organized.
- Consistency- Guarantees that all data accesses across an application exhibit consistent patterns, reducing mistakes and promoting dependability.
Conclusion
Read More: ASP.NET Core Interview Questions and Answers |
FAQs
- Generic repositories
- Specific repositories
- Composite repositories