Наследование от классов сущностей и расширение класса - PullRequest
1 голос
/ 11 февраля 2011

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

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

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

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

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

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

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

1 Ответ

3 голосов
/ 11 февраля 2011

Следует иметь в виду, что 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 # полностью удаляет функцию и все вызовы к ней из кода, как если бы она вообще никогда не была там. Это делает типы меньше и вызовы других свойств быстрее, так как не нужно беспокоиться о вызове пустой функции.

...