Обязанности моего уровня обслуживания и хранилища - PullRequest
3 голосов
/ 10 марта 2011

На днях я задал этот вопрос:

Должен ли уровень хранилища возвращать объекты передачи данных (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, если это имеет значение.

Ответы [ 2 ]

0 голосов
/ 10 марта 2011

Один из разработчиков, которого я больше всего уважаю ayende (http://ayende.com/Blog/Default.aspx) сказал: видео "ORM - это ваш репозиторий" здесь -> http://community.devexpress.com/blogs/seth/archive/2011/03/09/interview-with-ayende-rahien-aka-oren-eini.aspx

Вопрос: вам действительно нужен шаблон репозитория? Просто мое мнение:)

0 голосов
/ 10 марта 2011

Правильно ли я сказал, что осуществление фактического доступа к данным по-прежнему является обязанностью уровня хранилища (как и должно быть), и что проекция на сериализуемую форму является обязанностью уровня обслуживания (так какдолжно быть)?

Да, сервисный уровень по-прежнему не имеет представления о том, как выполняется фактический доступ к данным (как это не должно быть).Звонки отправляются в SQL?Есть ли между ними слой кэширования?

Недостатком, который я вижу, является то, что вы можете получить несоответствие, когда сервисный уровень выполняет проекции, которые на самом деле не могут быть переведены в SQL, что ему не нужнобеспокоиться о том, или где он выполняет такие сложные проекции, что делает сомнительным, какой уровень осуществляет фактический доступ к данным.

Для этой проблемы я использую паттерн конвейера, который в основном представляет собой просто набор методов расширения надIProjectable, который может выполнять проверенные проекции.Затем в вашем слое serviceLayer вы можете просто написать свой запрос, используя композицию этих конвейерных методов, например:

var users = repository.GetUsers (). FilterByName ("Polity"). OrderByAge (). ToTransferObjects ();

...