суббота, 13 октября 2012 г.

Strongly-typed Expand and async queries.

Очередной рабочий день разбирался с особенностями WCF Data Services.

Как я уже раньше писал, клиентская часть по умолчанию использует ленивую синхронную подгрузку. Чтобы этого избежать, пишутся простенькие методы, которые делают явную загрузку (eager loading). Благодаря избавлению от ObservableCollection<T>, это сделать легко.
Сегодня в дополнение к методу WhereAsync добавил методы FirstOrDefaultAsync и CountAsync, т.к. именно эти методы востребованы членами моей команды (судя по количеству не очень красивого кода, где они это сделали через WhereAsync). Код ниже.

Вторая важная особенность -- типизированный Expand. Наш предыдущий мега-проект работает на WCF RIA Services + SL, поэтому все уже привыкли писать инклуды. Тут, казалось бы, заменяем слово Include на Expand - и вуаля! Как бы не так.
.Expand(a => a.Author)
.Expand(a => a.Customers.Select(c => c.Person))
Первый работает, второй нет. Сегодня работая с проектом заметил, что коллеги решили не париться и писать строковые, не-типизированные Expand'ы. Кровь взыграла: как же так, нарушение идеологии!
Нашёл вот здесь код для примера, допилил чуток, и вот он - метод Include!
Если кому пригодится, кинул на pasteBin.

Третья важная особенность - это не EF. Поскольку все привыкли к риа сервисам, возникает куча проблем на ровном месте, как-то:
  • сущность уже загружена сервисом, как мне её выцепить по Id? Снова лезть на сервисы?
  • надо сделать отмену изменений свойств сущности (Modified -> Unchanged). Как, заново брать её от сервисов?
  • хз есть сущность или нет. Подгружаем на всякий случай -- падает Exception: The context is already tracking a different entity with the same resource Uri.
  • в модели много FK связей. Присвоение навигационного свойства не меняет скалярный Id и наоборот. SetLink иногда помогает, иногда нет.
  • как сделать SaveChanges только для одного графа, не затрагивая другой? Несколько контекстов и attach/detach? Вы это серьёзно?
  • как писать валидацию? Дублировать код с обеих сторон? Пока делаем client-side only, но есть идея делать всё в одном месте: серверный EF, автоматическая генерация некоторых проверок в SQL и прокидывание на клиента с возможностью расширения на клиенте.
Короче, проблем хватает, наверное интереснее будет реализовать подмножество функций EF для решения описанных проблем, благо T4 имеются.

Комментариев нет:

Отправить комментарий