Question:
I'm new to the repository pattern, and I'm attempting to implement a new ASP.NET MVC application using it. I have some confusion when it comes to implementing a repository that "contains" / represents multiple entities. I've seen it stated that one should not have one repository per entity but instead one repository per aggregate root.
If my aggregate contains multiple entities (or tables, in my physical model), what would a basic ASP.NET MVC repository look like for this aggregate?
Example:
If it helps to have a concrete example to work with, let's say we have an application containing an aggregate, Employees. The Employees aggregate contains three entities, represented by three tables in the DB - Employees, EmployeeTypes, and EmploymentStatus.
Employee
========
EmployeeID (PK)
EmployeeFullName
EmployeeTypeCode (FK)
EmployeeTypes
=============
EmployeeTypeCode (PK)
EmployeeTypeCodeDescription
EmploymentStatus
================
EmployeeID (PK)
EmploymentStatusCode (PK)
EmploymentStatusStartDate (PK)
EmploymentStatusEndDate
This structure allows us to have employees, define what type of employee they are, and have a record of status (hired in 1 position, promoted to another position, fired, re-hired, etc.). In reality the structure would look different than this, but let's use it as the example.
An incomplete repository (this example is based on one given in Pro ASP.NET MVC 2 Framework, by Steven Sanderson) for one entity that would give us a list of employees and allow us to save an employee could be this interface:
public interface IEmployeesRepository
{
IQueryable<Employee> Employees { get; }
void SaveEmployee(Employee employee);
}
And this implementation (in this case using Linq to SQL; it could be NHibernate or Entity Framework):
using System;
using System.Data.Linq;
using System.Linq;
using MyApp.Domain.Abstract;
using MyApp.Domain.Entities;
namespace MyApp.Domain.Concrete
{
public class SqlEmployeesRepository : IEmployeesRepository
{
private Table<Employee> employeesTable;
public SqlEmployeesRepository(string connectionString)
{
employeesTable = (new DataContext(connectionString)).GetTable<Employee>();
}
public IQueryable<Employee> Employees
{
get { return employeesTable; }
}
public void SaveEmployee(Employee employee)
{
if (employee.EmployeeID == 0)
employeesTable.InsertOnSubmit(employee);
else if (employeesTable.GetOriginalEntityState(employee) == null)
{
employeesTable.Attach(employee);
employeesTable.Context.Refresh(RefreshMode.KeepCurrentValues, employee);
}
employeesTable.Context.SubmitChanges();
}
}
}