На днях я задал этот вопрос:
Должен ли уровень хранилища возвращать объекты передачи данных (DTO)?
Ответ (ну, всего одинчеловек, но у меня уже было предчувствие, что это не очень хорошая идея) было то, что нет, позже хранилище не должно иметь дело с объектами DTO (их цель - просто отправка по проводам), а уровень обслуживания долженразобраться с этим.
Теперь я придумаю конструкцию, по которой мне нужно ваше мнение.Идея состоит в том, что, когда это имеет смысл, уровень хранилища может возвращать тип интерфейса, который я определил, под названием IProjectable
.Это оборачивает запрос (уровень хранилища еще не выполняет запрос), но не позволяет потребителю изменить запрос (это не IQueryable
), просто выполнить операции проекции с ним (пока для меня только First
иToPagedList
), который будет выполнять проекцию и фактически выполнять запрос.
Итак, что-то вроде этого в репозитории:
public IProjectable<User> GetUser(int id)
{
var query = from u in Set<User>()
where u.UserID == id
select u;
return query.AsProjectable();
}
А на уровне обслуживания что-то вроде этого:
var dto = repository.GetUser(16).Single(u => new SimpleUserDto
{
FullName = u.FirstName + " " + u.LastName,
DisplayAddress = u.Address.Street + u.Address.HouseNumber,
OrderCount = u.Orders.Count()
});
return dto;
Правильно ли я говорю, что выполнение фактическогоОтветственность за доступ к данным здесь по-прежнему лежит на уровне хранилища (как и должно быть), и что проекция на сериализуемую форму является обязанностью уровня обслуживания (как и должно быть)?
Единственный другой способ, которым ячтобы сделать это эффективно (возврат User
из хранилища и выполнение Count()
на его Orders
в слое обслуживания приведет к дополнительному запросу к базе данных) - определить типон обладает всеми этими свойствами и возвращает его из уровня хранилища, и просто не называйте его «Dto», что кажется глупым, поскольку он будет идентичен DTO, но не назван так же ради «чистоты».Таким образом, кажется, я могу взять свой пирог и съесть его по большей части.
Недостатком, который я вижу, является то, что вы можете получить несоответствие, когда сервисный уровень выполняет проекции, которые на самом деле не могут быть переведены в SQL, о которых ему не нужно беспокоиться, или гдеон выполняет такие сложные проекции, что делает сомнительным, какой уровень осуществляет фактический доступ к данным.
Кстати, я использую Entity Framework 4, если это имеет значение.