Как подключить контроллер к слою службы к слою репозитория

Допустим, у меня есть следующие сущности, которые сопоставляются с таблицами базы данных (каждое совпадающее имя свойства можно рассматривать как отношение PK/FK):

public class Person
{
  public int PersonID { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
}

public class Employee
{
  public int EmployeeID { get; set; }
  public int PersonID { get; set; }
  public int Salary { get; set; }
}

public class Executive
{
  public int ExecutiveID { get; set; }
  public int EmployeeID { get; set; }
  public string OfficeNumber { get; set; }
}

public class Contact
{
  public int ContactID { get; set; }
  public int PersonID { get; set; }
  public string PhoneNumber { get; set; }
}

Моя архитектура выглядит следующим образом: Контроллер вызывает уровень Сервис, который вызывает уровень Репозиторий.

У меня есть представление с именем AddExecutive, которое собирает следующую информацию: FirstName, LastName, PhoneNumber, Salary и OfficeNumber.

Каков наилучший способ фиксации этих данных с учетом моей архитектуры? Я думаю, что опубликую ViewModel, содержащую всю собранную мной информацию, и передам ее методу службы AddExecutive(AddExecutiveViewModel addExecutiveViewModel), затем в методе службы я создам новые экземпляры Person, Employee, Executive, и Contact и присоединю их друг к другу (Person объект) и передать ВСЕ данные методу репозитория AddExecutive(Person person). Затем метод репозитория просто зафиксирует данные. Это звучит правильно? Что было бы лучшим решением?


person Brian David Berman    schedule 27.10.2010    source источник


Ответы (2)


Пока вы поддерживаете разделение интересов, вы в порядке. Контроллер: связывает данные со службой/моделью Служба: обеспечивает соблюдение бизнес-логики, передает постоянство в репозиторий Репо: выполняет транзакции и запросы ACID.

Если ваша модель просмотра отделена от каких-либо проблем с инфраструктурой (например, POCO), у вас все должно быть хорошо, поскольку вы поддерживаете тестируемость.

person Slappy    schedule 27.10.2010
comment
Моя главная забота в отношении разделения задач (хе-хе) заключается в том, должен ли я иметь Службу и Репозиторий для каждой сущности или нет. Почему для меня нормально иметь только исполнительную службу и репозиторий? Это потому, что другие сущности могут быть связаны друг с другом? - person Brian David Berman; 27.10.2010
comment
Нет. Служба имеет ФУНКЦИОНАЛЬНЫЕ проблемы. (по сути, метод для каждого случая пользователя, грубо говоря). Служба принимает информацию в качестве входных данных, делаете ли вы это с помощью примитивов или пользовательского класса, зависит от вас. Если вы используете пользовательский класс, убедитесь, что он остается в сообщении, то есть: не создавайте большой пакет состояний для передачи ваших параметров. - person Slappy; 27.10.2010
comment
Считаете ли вы AddExecutiveViewModel, описанную выше, большим мешком состояния? - person Brian David Berman; 27.10.2010
comment
Концептуально это так, но практически это не так, так как это несвязанный специально созданный класс. Присвоение ему другого имени, по сути, исправит это. Попробуйте AddExecutive(ExecutiveViewModel ExecutiveViewModel), хе-хе. - person Slappy; 27.10.2010
comment
Спасибо. И вы согласны с тем, что метод Service — это хорошее место для заполнения истинных классов сущностей и передачи их (прикрепленных к объекту Person) в репозиторий? - person Brian David Berman; 27.10.2010
comment
Да, сервис может выполнять несколько вызовов репозитория одним методом. - person Slappy; 28.10.2010

Когда вы говорите о фиксации данных, вы говорите о единице работы. Итак, начните с этого:

public ActionResult AddExecutive(AddExecutiveViewModel addExecutiveViewModel)
{ 
    // simplified; no error handling
    using (var uow = new UnitOfWork()) // or use constructor injection on the controller...
    {
        // ???
        uow.Commit();
    }
    return RedirectToAction(// ...
}

Теперь ваши службы выходят из единицы работы (поскольку и единица работы, и репозитории совместно используют ObjectContext в фоновом режиме; ObjectContext — это «родная» единица работы EF). Итак, мы можем заполнить // ???:

public ActionResult AddExecutive(AddExecutiveViewModel model)
{ 
    // simplified; no error handling
    using (var uow = new UnitOfWork()) // or use constructor injection on the controller...
    {
        uow.EmployeeService.AddExecutive(model);
        uow.Commit();
    }
    return RedirectToAction(// ...
}

uow.Commit() представляет собой тонкую оболочку вокруг ObjectContext.SaveChanges(). В единицу работы вводится тот же ObjectContext, что и репозитории. Сервисы игнорируют EF.

Рабочий (хотя и на ранней стадии) пример см. в моем проекте репозитория/сервиса с открытым исходным кодом, Halfpipe.

person Craig Stuntz    schedule 27.10.2010