2013-02-20 2 views
9

У меня есть следующие слои, связанные с этим вопросом:Какой тип, возвращаемый при запросе нескольких объектов на уровне репозитория?

  • Service Layer (Использование IoC для вызова Repository)
  • домена модели (ПОКО/Доменные Сущности, определенные хранилища интерфейсов)
  • Repository Layer (EF. EDMX и внедренные хранилищами)

много раз это действительно прямо вперед: Repository слой запросов базы данных с помощью Entity Framework и возвращает IList<SomeDomainEntity> абоненту, который был Service Layer. Возвращаемый тип - это тип, определенный в модели домена.

Проблема Я бегу в когда мне нужно запросить через Pocos A, B и C и получить данные из всех должны быть возвращены. Поскольку я не обрабатываю какую-либо логику в репозитории, мне нужно вернуть эти данные на обрабатываемый уровень сервиса (либо напрямую, либо, скорее, путем вызова некоторой логики в модели домена). Однако у меня нет одного типа больше из результатов запроса в хранилище, чтобы вернуться к абоненту.

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

  1. Создать новый объект домена в модели предметной области, которая по существу представляет собой композицию из всех данных я запрошенной, так что этот новый один тип может быть возвращен. Это кажется неправильным для создания абразивных типов для удовлетворения запросов.
  2. Сделайте слой обслуживания называют отдельные хранилища на лицах, A, B, C отдельно, а затем иметь дело с данными каждого возвращенного объекта. Это похоже на большую работу.
  3. Создать ViewModel, чтобы вернуться. Мне это тоже кажется неуместным. Я активно использую классы ViewModel между моим уровнем обслуживания и уровнями пользовательского интерфейса, но никогда не видел, чтобы они использовались для возврата из репозитория.

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

Спасибо!

+1

Я бы выбрал вариант 1. Создавайте представления на основе ваших запросов и сопоставляйте их с новыми моделями домена. – Romoku

ответ

8

Если эти лица являются связанными и вы запрашиваете их все в одном месте, то вы должны попытаться найти aggregate root из них в вашей модели домена или, если он не существует еще вы должны ввести новую, а вы сказали в первом варианте. Это не так, пока это имеет смысл. Он должен моделировать концепцию домена, и у вас, вероятно, есть одно, потому что вы создали этот метод репозитория.

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

Вы, наверное, слышали о концепции navigation properties и eager loading, но я пишу это здесь, потому что это может быть другой ответ на свой вопрос (я не вижу вашу модель предметной области)

Я не пошел бы с треть предложение (создать модели представления в репозитории), потому что это разрывает разделение.

+1

Спасибо за помощь, что многое проясняет. Очень маленький вопрос - разделите ли вы агрегированные корневые объекты в свою собственную папку, чтобы сказать «AggregateRootEntities» для разграничения? – atconway

+2

Нет, различие не такое уж резкое, они большую часть времени являются гражданами первого класса :), но это не слишком важно, так что организуйте его так, как вы себя чувствуете. –

+0

Таким образом, разрешение на размещение в папке «DomainEntities» или «Entities» также будет приемлемым? Значит, мне не нужно так четко определять их как совокупные корневые сущности. – atconway

1

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

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

Предлагаю вам взглянуть на «AutoMapper». Я думаю, что это будет действительно полезно для вас

http://www.codeproject.com/Articles/61629/AutoMapper

http://lostechies.com/jimmybogard/2009/01/23/automapper-the-object-object-mapper/

+0

Я действительно использую DTO и ViewModels в * верхних * слоях моей архитектуры, но мой вопрос действительно фокусировался на слоях * lower *, включая репозиторий и модель домена. – atconway

+0

Я думаю, что ваш уровень репозитория должен знать только о сущности домена. Это работа другого уровня (прикладной уровень в DDD) для сопоставления и подготовки этих данных для представления –

3

Различные объекты могут относиться друг к другу Whithout одна из них совокупный корень. Для этих запросов используются службы. Я обычно делаю что-то вроде этого:

public class MyService 
{ 
    IEnumerable<UserWithMessages> Find() 
    { 
     var messages = _messageRepository.FindAll(); 
     var userIds = _messages.Select(x => x.UserId).Distinct().ToArry(); 
     var users = _userRepository.Find(userIds); 
     return users.Select(x => new UserWithMessages(x, messages.Where(x => x.UserId == x.Id)); 
    } 
} 

Это всего лишь два запроса БД, которые могут использовать индексы в БД. Так что это должно быть довольно быстро.

+0

Чтобы отобразить этот пример в моем примере, у меня уже были бы классы с именем 'messages' и' users'. Однако 'UserWithMessages' - это то, что мне нужно было бы создать и действовать как совокупный корень, составляющий некоторые элементы из двух отдельных классов, правильно? – atconway

+0

это правильно – jgauffin

Смежные вопросы