Какой тип возвращать при запросе нескольких объектов в слое Repository?

У меня есть следующие слои, вовлеченные в этот вопрос:

Сервисный уровень (использование IoC для вызова репозитория)Доменная модель (POCO / доменные объекты, определенные интерфейсы репозитория)Уровень репозитория (EF .edmx и реализованные репозитории)

Много раз этоЭто действительно просто: слой репозитория запрашивает базу данных через Entity Framework и возвращаетIList вызывающей стороне, которая была Service Layer.тип возвращается тип, определенный в модели предметной области.

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

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

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

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

Спасибо!

 Dustin Kingen20 февр. 2013 г., 18:28
Я бы выбрал вариант 1. Создание представлений на основе ваших запросов и сопоставление представлений с вашими новыми моделями доменов.

Ответы на вопрос(3)

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

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

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

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

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

 Pablo Rodríguez21 февр. 2013 г., 14:20
Я думаю, что ваш слой хранилища должен знать только о доменных сущностях. Это'Работа другого слоя (прикладного уровня в DDD) для отображения и подготовки этих данных для просмотра.
 atconway20 февр. 2013 г., 19:42
Я на самом деле использую DTO и ViewModels вверхний слои моей архитектуры, но мой вопрос действительно сосредоточен наниже слои, включая репозиторий и модель предметной области.

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

public class MyService
{
    IEnumerable 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));
    }
}

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

 jgauffin21 февр. 2013 г., 18:59
это правильно
 atconway21 февр. 2013 г., 18:47
Чтобы сопоставить этот пример с моим примером, у меня уже есть классы с именемmessages а такжеusers, тем не мениеUserWithMessages что-то, что я должен был бы создать и действовать как совокупный корень, составляющий определенные элементы 2 отдельных классов, правильно?
Решение Вопроса

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

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

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

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

 Peter Porfy20 февр. 2013 г., 22:43
Нет, различие не такое резкое, большую часть времени они первоклассные граждане :), но это не так.это слишком важно, так что организуйте это так, чтобы вам было удобно.
 atconway20 февр. 2013 г., 22:14
Спасибо за помощь, это многое проясняет. Действительно небольшой вопрос - вы разделяете объединенные корневые объекты в их собственную папку, скажем:AggregateRootEntities' для различия?
 Peter Porfy20 февр. 2013 г., 23:13
Да. Они есть 'агрегированные корневые объекты потому что вы используете их таким образом.
 atconway20 февр. 2013 г., 22:58
Таким образом, позволяя им проживать вDomainEntities' или же 'Сущности папка тоже подойдет? Смысл, я ненужно так четко определить их как совокупные корневые объекты.

Ваш ответ на вопрос