Общие классы DAL / BLL

В настоящее время я создаю классы уровня доступа к данным и уровня бизнес-логики для нашего нового приложения, и у меня есть вопрос (очевидно). Во-первых, вот некоторые детали, которые могут помочь:

  • Использование Entity Framework 5 для классов модели и доступа к данным
  • Каждый «слой» разделен на разные библиотеки классов и пространства имен (например, App.Model, App.DAL, App.BLL).

Начав с DAL, я решил написать базовый класс для наследования всех классов DAL.

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();
    }
}

Как вы увидите, базовый класс реализует универсальный тип, который должен быть типом модели, за работу с которой отвечает класс DAL. Используя универсальный тип, в конструкторе он создает DbSet, используя тип универсального аргумента, который используется в предопределенных CRUD-подобных виртуальных функциях ниже (добавление, получение и т. Д.).

И тогда у меня возникла идея - подожди минутку ... поскольку он общий, мне действительно не нужно реализовывать классы DAL для каждой отдельной модели. Я могу написать что-то вроде этого:

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

... которую я могу использовать для любой из моделей. Хорошо, перейдем к уровню бизнес-логики. Я также создал базовый класс для BLL:

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();
    }
}

... который использует GenericDAL для выполнения своей работы. Таким образом, я просто написал класс GenericBLL, который выглядит так:

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

А чтобы проверить это, простое консольное приложение:

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

... где "ADMIN" - это тип модели. Работает как шарм.

Идея заключалась в том, чтобы избежать необходимости писать классы DAL / BLL для каждой отдельной модели, если только это не требует дополнительных функций. Может кто-нибудь сказать мне, почему я НЕ БУДЕМ делать это таким образом? Я думаю, что общие классы DAL / BLL выполнят свою работу, а также сэкономят время разработки.

Спасибо за уделенное время.


person zday    schedule 21.02.2013    source источник


Ответы (2)


Что ж, одним из недостатков является то, что если вы решите добавить некоторые бизнес-правила позже, вам придется переключить тип с GenericBLL [Whatever] на WhateverBLL.

Очевидным решением этой проблемы является создание класса, унаследованного от GenericBLL [Whatever]. Нравится:

public class WhateverBLL : GenericBLL<Whatever>

и используйте вместо этого этот класс.

person Emil Lundin    schedule 21.02.2013
comment
Правильно. Если для модели требуется нечто большее, чем стандартные грубые функции, я бы реализовал для нее специальный класс BLL. Многие из необходимых функций для моделей очень просты. Так что универсальные классы будут служить много. - person zday; 21.02.2013
comment
Я бы рекомендовал вам с самого начала написать конкретные классы BLL для всех ваших сущностей. Они просто должны быть заглушками, унаследованными от вашего базового класса. Таким образом, вам не придется менять типы, если вы решите добавить бизнес-логику позже. - person Emil Lundin; 22.02.2013
comment
Отличное предложение - имеет большой смысл. Спасибо! - person zday; 05.03.2013

Прямо сейчас ваш BLL особо не добавляет ценности. Каждый вызов - это просто переход на другой уровень. Может быть, дело в простоте вашего приложения (и спасибо вашим счастливым звездам за то, что вам так повезло), или, может быть, у вас есть то, что я бы назвал реальной бизнес-логикой, живущей в другом месте.

Для меня бизнес-логика - это все, что делается до сохранения данных, все, что делается после получения данных, и тому подобное. Решения, развилки на дороге, предпринятые действия. На самом деле сохранение и извлечение данных обычно чрезвычайно тривиально по сравнению.

Итак, когда я смотрю на ваш общий базовый класс DAL, я думаю, что это хорошее начало. Я бы, наверное, извлек из него интерфейс, чтобы заменить его при тестировании. На данный момент ваш класс, наследующий базовый, не добавляет никакого значения. Не создавайте слои и классы просто ради этого, убедитесь, что это добавляет ценности и в некоторой степени облегчает вашу жизнь.

Когда я смотрю на ваш общий класс BLL, я думаю, что ваша настоящая бизнес-логика спрятана в коде некоторой формы или внутри файла класса в консольном приложении. Хотя вполне возможно, что могут существовать общие применимые функции, которые зависят только от типа, я не думаю, что один класс - это то, что вам нужно. Я предлагаю пересмотреть свою реальную бизнес-логику. Вероятно, простой сквозной слой в DAL - не так.

person Anthony Pegram    schedule 21.02.2013
comment
Фактически еще не реализована бизнес-логика. Это самый старт проекта. Поскольку я знаком с этим шаблоном, приложение, использующее BLL, не должно знать о DAL. Таким образом, основные функции crud - это всего лишь минимум того, что требуется на данный момент. Когда необходимо добавить новую бизнес-логику, я должен написать класс BLL, специфичный для этой модели, который будет обладать необходимой функциональностью. Идея в том, что мне нужно будет писать эти конкретные классы только тогда, когда это необходимо, а не для каждого из них. Многое из того, что нам нужно, действительно является основным для некоторых моделей. - person zday; 21.02.2013