Шаблон репозитория, POCO и бизнес-объекты - PullRequest
16 голосов
/ 15 сентября 2010

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

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

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

Ответы [ 3 ]

33 голосов
/ 15 сентября 2010

Сначала наблюдение за шаблоном проекта Asp.net MVC

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

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

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

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

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

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

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

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

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

8 голосов
/ 03 января 2011

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

Итак, ваш проект QandA

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

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

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

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

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

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

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

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

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

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

class QuestionForm
{
 public string Title
 public string QuestionContent
}

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

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

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

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

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

5 голосов
/ 15 сентября 2010

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

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

У вас может быть один класс хранилища или хранилище для каждой сущности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...