Репозиторий, Конвейер, бизнес-логика и модель домена - как я могу их совмещать?
Я разрабатываю приложение N-уровня, и я столкнулся с трудностью, с которой у вас может быть решение. Уровень представления - MVC.
Мой ORM выполняется с использованием LinqToSQL - это отдельный проект, который обслуживает репозитории.
Каждый репозиторий имеет интерфейс и не менее 1 конкретную реализацию.
Репозитории имеют следующие методы: FindAll(), Save(T entity), Delete(int id)
FindAll()
возвращает IQueryable какого-либо типа, что означает, что он возвращает запросы, к которым я могу применить фильтры.
Отображение ORM было выполнено с использованием методологии Database First, где сначала были созданы таблицы, а затем SQL Server были созданы классы.
Я добавил слой Pipeline, который работает с репозиториями. Он применяет дополнительные фильтры к запросам. Например. OrderRepository.FindAll().Where(o => o.CustomerId == 10)
Pipeline также возвращает IQueryable какого-либо типа, что означает, что я могу передать его дальше по слою и делать с ним больше.
В этот момент я бы хотел перейти на уровень BusinessLogic, но я больше не хочу работать с сущностными моделями, я хочу преобразовать модель сущности в модель домена. Это означает, что я могу добавить валидацию к модели и использовать эту модель в уровне представления. Модель не может быть определена в проекте MVC, поскольку она будет зависеть от уровня представления, так что no.
Я уверен, что бизнес-логика (поведение) и модель должны храниться отдельно от уровня конвейера, данных и представления. Вопрос в том, где?
Например, конвейер имеет три метода:
1. FindByCustomerId
2. FindByOrderId
3. FindBySomethingElse
Все эти методы возвращают IQueryable of Order. Мне нужно преобразовать это в модель домена, но я не хочу делать это для каждого метода, поскольку он не будет поддерживаться.
Я чувствую, что эта модель достаточно надежна и масштабируема. Я просто не вижу, какое место лучше всего подходит для сопоставления объектов с моделью домена и наоборот.
Спасибо
Ответы
Ответ 1
Прежде всего, если вы применяете принципы разработки Driven Driven Design, вы не должны иметь уровень BusinessLogic в своем приложении. Вся бизнес-логика должна жить внутри вашей модели домена.
Но достичь LinqToSQL довольно сложно, поскольку он не поддерживает сопоставление наследования, и вам придется иметь дело с частичными классами, чтобы поместить бизнес-логику в ваш домен. Поэтому я настоятельно рекомендую рассмотреть переход с LinqToSQL на NHibernate или Entity Framework Code First. В этом случае вам также не придется преобразовывать вашу модель персистентности в вашу модель домена и наоборот.
Если вы все еще хотите преобразовать, вы можете взглянуть на Automapper
Ответ 2
С точки зрения домена вам понадобится factory, чтобы преобразовать ваш "объект базы данных" в объект модели домена.
Когда вы думаете об обращении "сущностей базы данных" к объектам модели домена в конце вашего конвейера, вы должны понимать, что после преобразования в объекты модели домена (проекции) вы не сможете использовать IQueryable поскольку проекция будет инициировать выполнение вашего дерева выражений. Например, если вы вызываете FindAll для своей сущности базы данных клиента и затем конвертируете IQueryable в (или проецируете его) на объект домена клиента, который он выполнит (запрашивая содержимое всей вашей таблицы).
Ответ 3
Вот как я делаю проекты N-Tier. Эта архитектура имеет большое разделение проблем. Похоже, вы уже направились в этом направлении.
В проекте Mvc есть все ваши обычные объекты (контроллеры, ViewModels, представления, помощники и т.д.). Довольно просто. Все представления строго типизированы. Плюс мои измененные шаблоны T4, которые генерируют контроллеры, представления и ViewModels.
В проекте бизнес-модели у меня есть все мои бизнес-объекты и правила. Включаются интерфейсы, которые определяют функциональность репозиториев данных. Вместо того, чтобы иметь один репозиторий для каждого бизнес-объекта/таблицы, я предпочитаю группировать мои по функциональности. Все объекты, связанные с блогом, находятся в одном хранилище, а все объекты, связанные с фотогалереей, находятся в отдельном репозитории, а регистрация может быть в третьем.
Здесь вы можете разместить свой слой трубопровода.
В проекте Data я реализую эти интерфейсы репозитория данных. Вы можете использовать Linq2SQL без использования частичных классов. Расширение частичных классов Linq2SQL означает, что вы привязали ORM к вашей модели домена. То, что вы действительно не хотите делать. Вы хотите оставить эти созданные классы данных в области данных. Ниже приведен пример выбора Linq2SQL, который возвращает объект BusinessModel.
from t in Table
where t.Field == keyField
select new BusinessModel.DataObject
{
Id = t.Id,
Field1 = t.Field1,
Field2 = t.Field2
}
Если бы я был вами, я бы посмотрел на EntityFramework 4.1 с использованием подхода CodeFirst или с помощью NHibernate. Любой из них отобразит вашу модель данных в модель домена. Затем, чтобы сопоставить модели домена с моделями просмотра, вы можете использовать AutoMapper или написать собственный код или написать шаблон T4, который будет генерировать код отображения для вас.
Вы можете взять код, сгенерированный файлом dbml, в качестве отправной точки для ваших бизнес-объектов.
Ответ 4
В дополнение к комментариям xelibrion вы можете взглянуть на LightSpeed для ваших потребностей ORM. В настоящее время вы используете LinqToSQL, поэтому вы должны найти Lightspeed очень прямолинейно, так как он использует ту же идею.
http://www.mindscapehq.com/products/lightspeed
Если вы можете получить свои данные для сопоставления моделей, которые больше соответствуют форме, которую хотят высшие уровни, надеюсь, вы можете упростить ситуацию. Чем меньше сложностей в системе, тем меньше возможностей для ошибок.
Ответ 5
Все эти методы возвращают IQueryable Порядок. Мне нужно преобразовать это в модель домена, но я не хочу делать по каждому методу, поскольку это не будет mainteinable.
Это не настоящая оценка и, вероятно, блокирует вас от правильного решения.