Search code examples
c#.netgenericsdata-access-layerbusiness-logic-layer

Generic DAL / BLL Classes


I'm currently building the Data Access Layer and Business Logic Layer classes for our new application, and I have a question (obviously). First, here are some details that may help:

  • Using Entity Framework 5 for Model classes and data access
  • Each "layer" is separated in different class libraries and namespaces (i.e App.Model, App.DAL, App.BLL)

Starting with the DAL - I decided to write a base class for all DAL classes to inherit.

public abstract class DALBase<T> : IDisposable
{
    protected AppEntities context;
    protected DbSet set;

    public DALBase()
    {
        context = new OECCORPEntities();
        set = context.Set(typeof(T));
    }

    protected virtual void Save()
    {
        context.SaveChanges();
    }

    public virtual void Add(T model)
    {
        set.Add(model);
        Save();
    }

    public virtual T Get(int id)
    {
        return (T)set.Find(id);
    }

    public virtual List<T> GetAll()
    {
        return set.OfType<T>().ToList();
    }

    public virtual void Delete(int id)
    {
        T obj = Get(id);
        set.Remove(obj);
        Save();
    }

    public virtual void Update()
    {
        Save();
    }

    public void Dispose()
    {
        context.Dispose();
    }
}

As you will see, the base class implements a generic type which should be the type of the model the DAL class is responsible for working with. Using the generic type, in the constructor it creates a DbSet using the type of the generic argument - which is used in the predefined CRUD-like virtual functions below (add, get, etc).

And then I got the idea - wait a minute... since it's generic, I really don't have to implement DAL classes for every single model. I can just write something like this:

public class GenericDAL<T> : DALBase<T>
{
    public GenericDAL() : base() {}
}

... that I can use for any of the models. OK, so on to the Business Logic Layer. I created a base class for BLL as well:

public abstract class BLLBase<T>
{
    protected GenericDAL<T> dal;

    public BLLBase()
    {
        dal = new GenericDAL<T>();
    }

    public virtual void Add(T model)
    {
        dal.Add(model);
    }

    public virtual T Get(int id)
    {
        return dal.Get(id);
    }

    public virtual List<T> GetAll()
    {
        return dal.GetAll();
    }

    public virtual void Delete(int id)
    {
        dal.Delete(id);
    }

    public virtual void Update()
    {
        dal.Update();
    }
}

... which uses the GenericDAL to do its work. So in a simular fashion, I just wrote a GenericBLL class that looks like this:

public class GenericBLL<T> : BLLBase<T>
{
    public GenericBLL() : base() { }
}

And to test it, a simple console application:

class Program
{
    static void Main(string[] args)
    {
        GenericBLL<ADMIN> bll = new GenericBLL<ADMIN>();
        List<ADMIN> admins = bll.GetAll();
    }
}

... where "ADMIN" is the model type. Works like a charm.

The idea behind this was to avoid having to write DAL / BLL classes for every single model, unless it needed extra functionality. Can someone tell me why I WOULDN'T want to do it this way? I think the generic DAL / BLL classes would get the job done and also save development time.

Thank you for your time.


Solution

  • Well, one drawback is that if you decide to add some business rules later on you would have to switch the type from GenericBLL[Whatever] to WhateverBLL.

    An obvious solution to this is to create a class that inherits from GenericBLL[Whatever]. Like:

    public class WhateverBLL : GenericBLL<Whatever>
    

    and use this class instead.