1

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();
        }
    }
}
2
  • Check out this question too stackoverflow.com/questions/3829401/… Commented Feb 1, 2011 at 17:43
  • Thanks Nick DeVore -- The book and article that are referenced by the answer to that question I've already read. Unfortunately, neither seem to talk about multiple entities within a repository. Commented Feb 1, 2011 at 18:45

1 Answer 1

1

Your repository shouldn't look any different. It's interface should not at all expose the fact that your Aggregate Root has whatever particular child sub-entities. Obviously, the implementation of the repository will have to deal with changes to those child entities, but the interface your Employee repository presents should have nothing at all to do with those sub-entities. They should be encapsulated inside the Aggregate Root.

Sign up to request clarification or add additional context in comments.

2 Comments

qstarin: I'm not sure I understand. Can you elaborate in the context of the example I've given? Say that an employee is promoted, and we want to record that fact. To correctly implement the Repository pattern, we'd probably want an UpdateEmployeeStatus method in our Employee repository, right, rather than a new EmploymentStatus repository with its own method?
No. Definitely not. That is an anti-pattern that tends to lead to an anemic domain. It puts your domain logic in the repository, but where it belongs is in the entities. UpdateEmployeeStatus belongs in Employee. Employee is responsible for modifying its own state. And the repository is simply there to pick up on the changes in state and persist them (which is why mature ORM's like NHibernate are so useful, they handle picking up the state changes in your entites automatically).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.