Где конвертировать бизнес-модель для просмотра модели? - программирование
Подтвердить что ты не робот

Где конвертировать бизнес-модель для просмотра модели?

В моем приложении ASP.NET MVC я использую шаблоны единиц работы и репозитория для доступа к данным.

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

  • Репозиторий возвращает бизнес-модель контроллеру, эта модель сопоставлена с моделью просмотра, или
  • Сам репозиторий преобразует бизнес-модель для просмотра модели и затем возвращается в контроллер.

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

С другой стороны, я думаю, поскольку мой репозиторий называется UserRepository (например), он должен возвращать бизнес-модель напрямую, а не какую-то модель, которая полезна только для одного представления.

Какой из них вы считаете лучшей практикой для больших проектов? Есть ли альтернативный способ?

4b9b3361

Ответ 1

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

Вот как выглядит типичное действие контроллера GET:

public ActionResult Foo(int id)
{
    // the controller queries the repository to retrieve a domain model
    Bar domainModel = Repository.Get(id);

    // The controller converts the domain model to a view model
    // In this example I use AutoMapper, so the controller actually delegates
    // this mapping to AutoMapper but if you don't have a separate mapping layer
    // you could do the mapping here as well.
    BarViewModel viewModel = Mapper.Map<Bar, BarViewModel>(domainModel);

    // The controller passes a view model to the view
    return View(viewModel);
}

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

[AutoMap(typeof(Bar), typeof(BarViewModel))]
public ActionResult Foo(int id)
{
    Bar domainModel = Repository.Get(id);
    return View(domainModel);
}

Фильтр настраиваемых действий AutoMap подписывается на событие OnActionExecuted, перехватывает модель, переданную в результат просмотра, вызывает слой отображения (AutoMapper в моем случае), чтобы преобразовать его в модель представления и заменить его для представления. Представление, конечно же, строго типизировано для модели представления.

Ответ 2

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

Затем вы можете использовать инструмент, например Automapper, чтобы автоматически сопоставлять свойства с вашей моделью просмотра и может избавиться от ручной код сопоставления. Этот подход очень полезен, если вы не хотите раскрывать все свойства бизнес-объекта или компилируете структуру для представления.

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

Отрывок из сообщения (атрибут делает преобразование в виде загрузочной модели для viewmodel):

[AutoMap(typeof(Product), typeof(ShowProduct))]
public ActionResult Details(int id)
{
    var product = _productRepository.GetById(id);

    return View(product);
}

Ответ 3

Как уже упоминалось в других ответах, AutoMapper является хорошим решением.

Однако вы также можете написать методы расширения для преобразования вашей сущности во ViewModel и наоборот. Может быть, это лучше для небольших проектов с меньшим количеством классов Entity и Model.

Пример:

public static class Extension
{
    public static MyViewModel ToModel(this MyEntity x)
    {
        return new MyViewModel
        {
            Id = x.Id,
            Name = x.FirstName + " " + x.LastName,
            UserId = x.User?.Id
        };
    }
}

И использовать:

// NOTE: "MyEntityTable" is of type "MyEntity"

List<MyViewModel> toReturn = _db.MyEntityTable
                  .Include(x => x.User) // Include other tables to join.
                  .Select(x => x.ToModel())
                  .ToList();