I just read Adrian Halls Zumo-Book at aka.ms/zumobook. In chapter three he talks about relational data and suggests that it might not be best practice expanding relational data when querying objects with one to many relations due to high bandwidth usage when it comes to developing mobile clients against Azure App Services for instance.

One of his solutions is creating a third table that holds both parents' and childrens' id and providing another controller which allows you querying relational data from client side.

On the pro-side - he says - is, that now you have a flat structure which works for offline sync scenarios (something you definetly would want to implement on your mobile client).

However, while I tried to implement this recipe, I stumbled accross this: I am using Azure Active Directory B2C for authentication and user management. So my controllers are decorated with the [Authorize] attribute and have access to the User property which - when casted to a ClaimsPrincipal object - contains the authorized users' sid.

As Adrian also suggests in chapter 2, I added sid properties to my dataobjects and whenever a post takes place, I transform the object by adding this sid server side. Also when getting, patching or deleting objects, my controller ensures that only the owner of the object may execute the respective operation.

For instance:

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);
}

I quite like that pattern…

If you read this far, thank you! Cuz, here (finally) is my question:

Instead of having to query against two or three tables from my client when trying to resolve one to many relationships and - by doing this - having to work with ids manually anyway, why can't I simply add this sid to any related data and have my controller select the correct data instead?

Let's assume this structure:

User

  • Id
  • Sid

Item

  • Id
  • Sid

UserItem

  • UserId
  • ItemId

Why should I go the long way around by doing something like this:

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;

Because, when inserting both user and item, my controller adds the authorized users' sid anyway, so I could simply query for all items instead and due to the controller filtering to the autorized users' sid anyway, I would get the very same list of items that belong to the user.

Am I missing something here?

0 Answers