Отношения один ко многим в службах приложений Azure - PullRequest
0 голосов
/ 28 мая 2019

Я только что прочитал Zumo-книгу Адриана Холла на aka.ms/zumobook. В третьей главе он говорит о реляционных данных и предполагает, что, возможно, было бы нецелесообразно расширять реляционные данные при запросах объектов с отношениями один-ко-многим из-за высокой пропускной способности, когда речь идет о разработке мобильных клиентов, например, на основе служб приложений Azure.

Одним из его решений является создание третьей таблицы , в которой хранится идентификатор родителей и детей, и предоставление другого контроллера , который позволяет запрашивать реляционные данные со стороны клиента.

Что касается сторонников, - говорит он, - то, что теперь у вас есть плоская структура, которая работает для сценариев автономной синхронизации (то, что вы определенно хотели бы реализовать на своем мобильном клиенте).

Однако, пытаясь реализовать этот рецепт, я наткнулся на это: Я использую Azure Active Directory B2C для проверки подлинности и управления пользователями. Таким образом, мои контроллеры имеют атрибут [Authorize] и имеют доступ к свойству User, которое - при приведении к объекту ClaimsPrincipal - содержит sid авторизованных пользователей.

Как Адриан также предлагает в главе 2, я добавил свойства sid к своим объектам данных и всякий раз, когда происходит post , я преобразую объект, добавляя эту сторону сервера sid. Кроме того, когда получает , исправляет или удаляет объекты, мой контроллер гарантирует, что только владелец объекта может выполнить соответствующую операцию.

Например:

public string Sid => ((ClaimsPrincipal)User).FindFirst(ClaimTypes.NameIdentifier).Value;

public void ValidateOwner(string id)
{
  var result = Lookup(id).Queryable.PerUserFilter(Sid).FirstOrDefault<User>();
  if (result == null)
  {
    throw new HttpResponseException(HttpStatusCode.NotFound);
  }
}

public Task<User> PatchUser(string id, Delta<User> patch)
{
  ValidateOwner(id);
  return UpdateAsync(id, patch);
}

public async Task<IHttpActionResult> PostUser(User item)
{
  item.Sid = Sid;
  User current = await InsertAsync(item);
  return CreatedAtRoute("Tables", new { id = current.Id }, current);
}

Мне очень нравится этот шаблон ...

Если вы прочитали это далеко, спасибо! Потому что, вот (наконец) мой вопрос:

Вместо того, чтобы запрашивать у двух или трех таблиц моего клиента при попытке разрешить отношения один ко многим и - делая это - приходится работать с идентификаторами вручную в любом случае , почему я не могу просто добавить этот sid к любым связанным данным и чтобы мой контроллер выбрал правильные данные вместо этого?

Предположим, эта структура:

Пользователь

  • Id
  • Sid

Пункт

  • Id
  • Sid

UserItem

  • UserId
  • ItemId

Почему я должен пройти долгий путь, выполнив что-то вроде этого:

var itemList = from i in Item
           let il = (from ui in UserItem where ui.UserId == UserId select ui.ItemId)
           where il.Contains(i.Id)
           select i;

Поскольку при вставке пользователя и элемента мой контроллер все равно добавляет sid авторизованных пользователей , поэтому я мог бы просто запросить все элементы вместо этого и из-за контроллера фильтруя по sid авторизованных пользователей в любом случае , я бы получил тот же список элементов, которые принадлежат пользователю.

Я что-то здесь упускаю?

...