Это плохо для картографа для получения данных из БД?
Я задаюсь вопросом: насколько сложной может быть абстракция картографа?
Допустим, у меня есть действие контроллера
ActionResult Find(QueryInputModel query)
с моделью выглядит так
class QueryInputModel
{
public string Text {get;set;}
public IEnumerable<string> RegionCodes {get;set;}
}
Помимо всего прочего, действие превращает входную модель в модель представления.
class QueryViewModel
{
public string Text {get;set;}
public IEnumerable<Region> Regions {get;set;}
}
class Region
{
public string Name {get;set;}
public string Code {get;set;}
}
где имена регионов в модели представления должны быть взяты из базы данных с использованием кодов во входной модели. Прямо сейчас это сделано QueryMapper.Map(src)
метод, который выглядит так
public QueryViewModel Map(QueryInputModel source)
{
var regions = regionRepository.Get(source.RegionCodes);
var result = new QueryViewModel {Text=source.Text, Regions=regions};
}
Правильно ли называть такую абстракцию Mapper? Можно ли смешивать прямое отображение и запросы к базе данных в одном методе?
2 ответа
Ну, вот мой взгляд на это. Исходя из того, что вы говорите, у вас есть сценарий использования "Найти детали региона из кодов регионов". Этот вариант использования имеет два входных порта и один выходной порт:
- Пользователь может ввести свой запрос через один входной порт.
- Отображение в БД из кодов регионов в детали региона - это еще один входной порт.
- Способ вернуть результаты пользователю - это выходной порт.
Вся логика, которую вы реализовали в своем Map
функция - это логика вашего варианта использования. Функция должна действительно выглядеть следующим образом.
public void FindRegionDetailsFromRegionCodes(IUserQuery userQuery,
IRegionMapper regionMapper,
IUserDisplay userResult) {
var regions = regionMapper.Get(userQuery.RegionCodes);
userResult.ShowResult(regions);
}
С:
interface IUserQuery {
IEnumerable<string> RegionCodes { get; }
}
interface IRegionMapper {
IEnumerable<Region> Get(IEnumerable<string> regionCodes);
}
interface IUserDisplay {
void ShowResult(IEnumerable<Region> regions);
}
Таким образом, код варианта использования касается только логики выполнения действия, а не деталей того, как выполняется каждая из этих вещей. Вы можете выставить свой сервис через сетевой порт TCP (путем соответствующей реализации IUserQuery
а также IUserDisplay
), или рассчитать детали, бросив пару D20 и поиск случайного файла на C:\
и разведение хомяков (путем надлежащего осуществления IRegionMapper
).
Теперь правда в том, что вы выставляете этот вариант использования в действии контроллера? Хорошо. Поэтому действие вашего контроллера может вызвать FindRegionDetailsFromRegionCodes
передавая это:
- Ваш
QueryInputModel
, осуществляяIUserQuery
- Ваш
QueryViewModel
, осуществляяIUserDisplay
- Ваш
RegionRepository
(Я полагаю, это имя класса), реализуяIRegionMapper
Копирование Text
от ввода к представлению не касается вашего варианта использования. Это должно быть сделано вашими действиями. (в качестве вспомогательного аргумента к моей диссертации, если у вас есть в какой-то момент, чтобы скопировать другое поле, это не должно изменить код варианта использования)
Надеюсь это поможет. Чтобы ответить на ваш вопрос, настоящее отображение происходит в БД, поэтому я назвал только порт "БД" IRegionMapper
,
Ваше отображение между ViewModel и DataModel является ручным отображением, попробуйте использовать стороннее отображение предпочтений, такое как Automapper или Valueinjecter, оба также могут быть установлены Nuget в ваш файл проекта. Лично предпочитаю Valueinjecter, так как его легче кодировать и понимать.