ASP.NET MVC: BLL and DAL to Repository design

5.9k views Asked by At

We are moving from ASP.NET Web Forms to MVC 2.0. In most of our projects we have a typical setup to communicate with a database.

Common (objects/entities like 'SiteMenu' and 'Users')

Business Logic Layer (with calls to de Data Access Layer)

Data Access Layer

The DAL has a DatabaseHelper with common database operation, an OdbcHelper with database specific operations (eg MySQL) and a StoredProcedure class with all the stored procedures.

How is this design translated into a repository design? We want to use our own database helpers instead of NHibernate etc.

What would you suggest?

2

There are 2 answers

4
e36M3 On

You can maintain the same layered approach when moving to MVC. Your BLL that returns entities/objects can be your M in MVC. Often you'll see in samples where people create an instance of the repository directly in their Controller, in your case you'll be creating an instance of your BLL class.

0
Easy-Rider On

You could leverage repositories using every data access technology. An repository is abstraction over existing data access helpers / services, allowing decoupling of the business logic from the data access layer. Repositories used together with Query to enable filtering. It is often used together with unit of work to store the changes back into database.

A repository has at least:

  1. Get-object-by-key operation(s)
  2. Get-all-objects operation
  3. Get-first-object-by-query operation(s)
  4. Get-objects-by-query operation(s)

A very simple example :):

A. Product class , defined in Common:

public class Product
{
    public int Id { get; private set; }

    public string Code { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set; }
}

B. Classes for Query, IRepository and IUnitOfWork are defined in DAL.interfaces.dll or Common.dll (but NOT in DAL!).

public class Query
{
    public string Text { get; set; }
}

public interface IRepository<TEntity>
    where TEntity : class
{
    bool TryGet(int key, out TEntity value);

    TEntity this[int key] { get; }

    IEnumerable<TEntity> GetAll();

    bool TryGetFirst(Query condition, out TEntity value);

    TEntity GetFirst(Query condition);

    IEnumerable<TEntity> GetAll(Query condition);

    int Count { get; }
}


public interface IUnitOfWork
{
    void SetAdded(TEntity value); // Marks entity as added for further INSERT

    void SetRemoved(TEntity value); // Marks entity as removed for further DELETE

    void SetChanged(TEntity value); // Marks entity as modified for further UPDATE

    void Save(); // Save all the changes 
}

IUnitOfWork is aware of the changed entities. Save() calls an appropriate DatabaseHelper / OdbcHelper CRUD method for every changed entity in order to persist the changes in the database.

The implementation of IRepository<Product>, ... IRepository<EntityXY> and IUnitOFWork should be placed in DAL. The BLL then uses IRepository and IUnitOFWork in order to implement business (domain) logic. The BLL itself could be organized as service layer on the top of domain model, but it is out of the scope of the discussion :).

I hope my answer helps.

Please feel free to ask me a question ...

Links: Patterns of enterpise application architecture by Martin Fowler