Наследование от классов сущностей и расширение класса

Я использовал Entity Framework 4.0 для создания своего уровня доступа к данным. Затем я обнаружил, что мой уровень бизнес-логики имеет те же объекты, что и DAL, но с некоторыми расширениями (т. Е. Больше свойств, некоторые функции и проверка данных в установщиках...).

Я планировал использовать DAL и BLL в отдельных проектах и ​​искал наилучшую практику использования классов сущностей в BLL и предотвращения избыточности в коде.

Пока я искал и есть две основные идеи:

  1. расширение классов сущностей внутри одного проекта частичными классами
  2. Использование интерфейсов (реализуется классом сущностей и соответствующим классом BLL). Бывший более популярен среди программистов.

Недостатки вышеуказанных решений:

  1. Нам нужно добавить код в тот же проект как часть частичного класса. Это хорошо для добавления свойств и методов, но не подходит для переопределения чего-либо (т. Е. Добавления проверок перед установкой свойства на уровне бизнес-логики)
  2. Если модель сущностей изменяется, нам нужно снова извлечь интерфейсы из классов сущностей, а также необходимо еще одно изменение в классе, связанном с BLL (два ручных обходных пути).

Мой вопрос заключается в том, почему мы просто не наследуем наши классы BLL от соответствующих классов сущностей и не расширяем / не переопределяем их методы и свойства?

1 ответ

Решение

Необходимо помнить одну вещь: ORM, как и Entity Framework, на самом деле не создают простой слой доступа к данным (если смотреть через общую трехуровневую архитектуру). Они дают вам гораздо больше бизнес-уровня с немного более детальным уровнем контроля над взаимодействием доступа к данным. Я думаю, что можно утверждать, что EF по сути становится вашим DAL, а контекст и типы сущностей могут быть BLL.

Строку намного легче увидеть, если рассматривать ее с большей частью архитектуры MVC или MVVM, где у вас есть модель (ваш уровень EF), контроллер или модель представления (где находится бизнес-логика, которая инкапсулирует модель) и представление.

В любом случае, поскольку EF фактически должен создавать экземпляры типов сущностей напрямую, наследование не принесет вам большой пользы, поскольку EF не будет использовать ваш подтип в качестве возвращаемого объекта. Решение для проверки и подобных задач в EF состоит в том, чтобы использовать как частичные классы (о которых вы, очевидно, знаете), так и частичные методы. Шаблоны генерации кода по умолчанию в EF создают частичные методы для всех скалярных свойств для OnPROPERTYNAMEChanging а также OnPROPERTYNAMEChanged,

Например, если у вас есть int UserId недвижимость на вашем User Тип сущности, вы можете создать частичный класс, который выглядит следующим образом:

public partial class User
{
    partial void OnUserIdChanging(int newUserId)
    {
        // do something
    }

    partial void OnUserIdChanged()
    {
        // do something
    }
}

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

Другими словами, даже если вы можете зайти в код конструктора и посмотреть объявления для

partial void OnUserIdChanging(int value);
partial void OnUserIdChanged();

Если вы на самом деле не добавляете тело метода в функцию, то компилятор C# полностью удаляет функцию и все вызовы к ней из кода, как если бы ее никогда не было. Это уменьшает типы и ускоряет вызовы других свойств, поскольку не нужно беспокоиться о вызове пустой функции.

Другие вопросы по тегам