Entity Framework и разделение слоев

12

Я пытаюсь немного поработать с Entity Framework, и у меня возник вопрос относительно разделения слоев.

Я обычно использую подход UI -> BLL -> DAL, и мне интересно, как использовать EF здесь.

Мой DAL обычно будет что-то вроде

GetPerson(id)
{
    // some sql
    return new Person(...)
}

BLL:

GetPerson(id)
{
    Return personDL.GetPerson(id)
}

UI:

Person p = personBL.GetPerson(id)

Мой вопрос сейчас: поскольку EF создает мою модель и DAL, это хорошая идея, чтобы обернуть EF внутри моего собственного DAL или это просто пустая трата времени?

Если мне не нужно оборачивать EF, я бы все равно поместил свой Model.esmx в его собственную библиотеку классов или было бы хорошо просто поместить его в мою BLL и поработать там?

Я не могу понять причину, чтобы обернуть EF в свой собственный DAL, но я хочу знать, что делают другие люди.

Таким образом, вместо того, чтобы иметь вышеупомянутое, я пропустил бы DAL и просто сделал бы:

BLL:

GetPerson(id)
{
    using (TestEntities context = new TestEntities())
    {
            var result = from p in context.Persons.Where(p => p.Id = id)            
                    select p;
    }
}

Что делать?

Томас
источник

Ответы:

13

В качестве примера вы приводите едва ли многоуровневую архитектуру. Я знаю, что это намеренно упрощено, но:

Ваш уровень презентации напрямую связан с сущностью Person. Это нормально только в самых простых случаях, и определенно не когда вы пытаетесь определить свои слои.

Метод GetPerson также использует довольно плохую практику создания нового контекста для каждого вызова. Вы должны получить контекст в конструкторе, и он будет предоставлен вашим контейнером IOC.

Простая, но эффективная структура, которую я использовал:

  • Project.Core - содержит модели представления и интерфейсы.
  • Project.DAL - с моим EDMX и сгенерированным кодом.
  • Project.BLL - бизнес-логика.
  • Project.Web - само веб-приложение.

Важно отметить, что:

  • Ядро не зависит от любого другого решения.
  • DAL не зависит от любого другого решения.
  • Project.Web зависит от Core, но не от DAL или BLL.
  • BLL зависит от Core и DAL.
Борис Янков
источник
1
Ядро будет выглядеть как слой бизнес-объекта.
sq33G
Это в значительной степени то, что я использую, однако, я бы добавил дополнительные библиотеки DLL для обслуживания объявлений интерфейса. Таким образом, вы только ссылаетесь на интерфейсы (и используете что-то вроде [url = unity.codeplex.com/]Unity[/url] для DI), и вы можете быть уверены, что нет никаких странных зависимостей, которые вы случайно вызвали.
Эд Джеймс
Обычно без EF я создаю свой собственный класс Person в слое «Model», поэтому у меня есть UI, BLL, DAL и Model, где: UI знает BLL и Model. BLL знает DAL и модель. DLL знает модель. Вы также создаете свои собственные "модели представления", и почему вы просто не используете те, которые генерирует EF? (Я знаю, что это противоречит многоуровневой архитектуре, но сколько раз вы фактически переключаетесь на способ получения данных?)
Томас
@Thomas, оборачивающий модели представления во что-то абстрактное, значительно упростит модульное тестирование.
sq33G
3
модель! = посмотреть модель
Борис Янков
2

Вам не нужно ничего оборачивать в EDMX.

Если вы можете предвидеть возможность перехода с EF на какой-либо другой подход, вы можете расширить свои бизнес-объекты (используя преимущества частичных классов) для реализации интерфейсов, определенных на отдельном уровне Business Object.

Тогда из вашего кода вы будете иметь дело только с этими интерфейсами, а не с конкретными сгенерированными классами. Небольшой клейкий код мог бы понадобиться, чтобы скрепить это; что с EDMX может быть вашим DAL.

sq33G
источник
Так что, если я не предвижу никаких изменений от EF к другому подходу, мой код выше будет в порядке? Тогда я бы имел только интерфейс и BLL (где EDMX находится в BLL)?
Томас
Мой прагматичный ответ был бы да. С оговоркой, что вы, возможно, захотите поместить EDMX в свою маленькую сборку, если она будет большой и в основном статичной, так что вам не нужно будет перекомпилировать / перераспределять ее так часто.
sq33G
Ах, хороший момент по поводу перекомпиляции / перераспределения :)
Томас
2

Существует два основных подхода к наслоению: строгое наложение и расслабленное наложение.

Строго слоистый подход ограничивает взаимодействие компонентов одного уровня только с одноранговыми узлами и непосредственно со слоем ниже.

Расслабленное многоуровневое приложение ослабляет ограничения, так что компонент может взаимодействовать с компонентами любого нижнего уровня.

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

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

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

omarqa
источник