Шаблон хранилища, POCO и бизнес-объекты

Я знаю, что в шаблоне репозитория уже есть много streamов, но почему-то я чувствую, что мой вопрос немного другой. Может быть, потому, что вчера я впервые услышал слово POCO.

Мой вопрос в том, что, как правило, я добавляю и сохраняю методы в своих бизнес-объектах. Скажем, я пишу сайт Q / A, и у меня есть следующие сущности: вопросы, ответы и комментарии. Если бы я хотел использовать шаблон репозитория, мне в основном нужно сохранить только свойства в моих бизнес-сущностях (например, вопрос) и перенести мои операции в class репозитория (например, QuestionRepository), правильно? Если это так, означает ли POCO бизнес-объект с только свойствами?

Я использую Entity Framework 4.0, который создал мои сущности в коде edmx. Если бы я хотел использовать шаблон репозитория с этим, нет необходимости писать мои собственные бизнес-сущности (вопрос, ответ и т. Д.), Так как они уже созданы EF, правильно? Все, что мне нужно, это repository, чтобы делать CRUD? И у меня будет три хранилища для этого примера, по одному для каждого объекта?

У ваших объектов POCO все еще есть методы для них для операций, но эти операции будут относиться к проблемам бизнеса предприятия, а не к проблемам сохранения (CRUD). Если на вашем предприятии нет бизнес-операций, тогда да, это будут просто свойства.

Вам не нужно будет писать свои pocos с нуля, если вы их генерируете, но вы можете расширить их с помощью частичных classов для бизнес-операций и непостоянных или рассчитанных свойств.

У вас может быть один class репозитория или repository для каждого объекта.

Первое замечание о шаблоне проекта Asp.net MVC

Я должен сказать, что крошечное недоразумение с шаблоном проекта MVC в Visual Studio Asp.net. И это папка Model . Люди, не зная шаблон MVC, автоматически связывают это с моделью данных, а не с моделью приложения / презентации MVC. Это хорошо для простых приложений, где мы не различаем их, но не для чего-либо еще.

Давайте продолжим мой ответ

Когда я пишу приложения бизнес-уровня, я разделяю свое решение на 4 проекта (по крайней мере):

  • уровень представления – приложение ASP.NET ASP.NET, но я удаляю папку Model и имею все мои представления в виде сильных типов, чтобы избежать как можно большего количества магических строк
  • уровень обслуживания – процессы бизнес-логики
  • модель данных – модель данных, т.е. EF4 и репозитории, которые обращаются к этой модели
  • объектов – этот проект фактически имеет POCOs, которые используются для межслойной связи и любые интерфейсы, используемые различными уровнями (думаю, IoC)

Мой процесс запроса обычно выглядит очень чистым и работает таким образом:

  1. Когда выполняется запрос, мое действие controllerа MVC-controllerа Asp.net проверяет данные (объекты POCO), делает все, что необходимо для уровня представления, перед вызовом в службы.
  2. Услуга называется тем, что требует логики бизнес-процессов и обычно вызывает repository, чтобы что-то делать с данными.
  3. Репозиторий манипулирует данными в модели данных, а затем создает POCO из результатов, которые будут возвращены на уровень обслуживания.
  4. Сервисный уровень получает POCOs делает дополнительную логику, если это необходимо, и возвращает их обратно в презентацию.
  5. Презентация (controller) решает, какое представление отображать и предоставляет модель для этого конкретного вида и возвращает его. Конечно, вместо представления это может быть и любой другой результат.

Преимущество использования отдельных classов модели MVC в проекте Objects (вы не могли поместить их в папку Model из-за круговой ссылки на проект) заключается в том, что у меня могут быть classы с оптимизированной презентацией. Или лучше сказал: у меня есть ориентированный на бизнес процесс, а не централизованный.

Давайте объясним это с помощью примера: возьмите, например, просмотр регистрации пользователя. Он не может быть строго типизирован для User объекта модели данных. Зачем? Потому что он имеет два входа для пароля. Поэтому у меня может быть class модели приложения / презентации под названием UserRegistration хотя в модели данных ничего подобного нет. Его валидация работает совершенно по-другому по сравнению с User объектом модели данных. Если бы у меня была моя регистрация пользователя без сильного типа, мне пришлось бы выполнить действие моего controllerа со всеми параметрами каждого отдельного поля. Они не будут автоматически проверены, что означало бы, что я могу иметь большую поверхность ошибок. Кто-то может спешить писать код, но забыть о некоторых аспектах проверки.

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

Я был в очень похожем месте, как OP некоторое время назад, поэтому я расскажу о Роберте с некоторым кодом того, как я структурировал приложение asp.net mvc после изучения шаблона репозитория.

Таким образом, ваш проект QandA

У вас будет проект библиотеки classов под названием QandA.data , здесь вы создадите файл edmx и все classы инфраструктуры вашего сущ. Затем у вас есть repository для каждого объекта, например:

 public interface IRepository { T Save(T entity); void Delete(T entity); IQueryable GetAll(); T GetById(int id); } 

Тогда вы можете иметь либо фабрику, либо использовать Dependency Injection для получения фактически репозиториев. Так:

 class QuestionRepo : IRepository { //call xxxEntites and get/save/delete yourentities here. } static class RepositoryFactory { public static IRepository GetQuestionRepo() { return new QuestionRepo(); } } 

Затем в своем коде вызова (в вашем проекте asp.net) у вас есть

 IRepository qRepo = RepositoryFactory.GetQuestionRepo(); Question q = qRepo.GetById(1); 

Теперь преимущество выполнения вышеизложенного заключается в том, что ваш код вызова не имеет представления о том, как проходят объекты, поэтому вы можете создать макетный repository для тестирования своего приложения.

 static class RepositoryFactory { public static IRepository GetQuestionRepo() { return new FakeQuestionRepo(); //create your own fake repo with some fixed fake data. } } 

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

Кроме того, о чем говорит Робер в своем вопросе, есть ViewModel. Таким образом, вы не сделали бы строго типизированную страницу типа Вопрос. Так что у тебя есть

 class QuestionForm { public string Title public string QuestionContent } 

Ваша страница будет иметь тип QuestionForm но в вашем controllerе создания вы берете данные из формы вопроса, заполняете их в свой объект Question и отправляете их через repository.

 [HttpPost] public ActionResult Create(QuestionForm quesfrm) { IRepository qRepo = RepositoryFactory.GetQuestionRepo(); Question ques = new Question { AskedDate = DateTime.Now, Title = quesfrm.Title, Content = QuestionContent } qRepo.Save(ques); } 

Роберт упоминает одну из причин, почему вы это сделаете, есть еще несколько причин, и вы можете больше узнать о моделях просмотра на SO. Также проверьте код для nerddinner

Вы можете захотеть увидеть эти SO-вопросы:
Должны ли хранилища реализовать IQueryable ?
Шаблон репозитория: один class репозитория для каждого объекта?

Надеюсь, это помогло.

  • Почему структура Entity Framework не может видеть информацию о столбце хранимой процедуры?
  • Entity Framework 4 - AddObject vs Attach
  • Обнаружено, что
  • Entity Framework: Где я могу расширить CSDL / MSL?
  • Объекты самоконтроля и объекты POCO
  • Создание динамических запросов с инфраструктурой сущностей
  • Зачем повторно инициировать DbContext при использовании Entity Framework?
  • Использование MySql с Entity Framework 4 и Code-First Development CTP
  • Является ли DbContext таким же, как DataContext?
  • Уже есть открытый DataReader, связанный с этой Командой, который должен быть закрыт первым
  • Преобразование String в Int в EF 4.0
  • Давайте будем гением компьютера.