Question

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.

Was it helpful?

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.

OTHER TIPS

Right now, your BLL isn't particularly adding value. Every call is simply a pass-through to another layer. Maybe it's the simplicity of your application (and thank your lucky stars that you are so lucky), or maybe you have what I would classify as the actual business logic living elsewhere.

Business logic to me is everything that is done up to the point of persisting data, everything that is done after retrieving data, and things like that. The decisions, the forks in the road, the actions that are taken. Actually saving and retrieving data is typical extremely trivial by comparison.

So as I look at your generic DAL base class, I think it's a fine start. I would probably extract an interface from it so I could replace it when testing. For now, your class that inherits the base isn't adding any value. Do not create layers and classes simply for the sake of it, be sure it adds value and makes your life easier in some way.

As I look at your generic BLL class, I think you probably have your real business logic tucked away in the codebehind on some form, or inside a class file in a console app. While it's certainly possible that there could be generically applicable functionality that only varies on the type, I don't think one class is where you want to be. My suggestion here is to reconsider what you think is your actual business logic. A simple pass-through layer to the DAL probably isn't it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top