If you've been working with related items, you may have found that it's a bit inconvenient to use right now. Specifically:

  • To set up a two-way-link between objects, you need to insert one, insert the second with related items, and then update the first one with a related item link.
  • You have to physically set up the links for every object (ie add a HealthRecordItemRelationship to CommonData.RelatedItems) - there's no helper to do it, and it's hard for us to write one.
  • You have to fetch each related item separately

We're having some discussions around how to fix the first one, and, if possible, the other two as well. We had originally thought that we would simply modify the platform NewItems() call to have a way to say "link all of these together using related items", but it turns out that there's no simple way to do that, and the complex ways have architectural implications we don't like.

So, we're considering a different scheme. In this scheme, rather than linking together using the platform-generated key (ie CommonData.Key.Id), we would link together using an application-generated client-id instead. So, to link two items together, you would do the following:

  1. Create instance of object a
  2. Create instance of object b
  3. a.CommonData.ClientId = Guid.NewGuid();
  4. b.CommonData.RelatedItems.Add(a.CommonData.ClientId);
  5. b.CommonData.ClientId = Guid.NewGuid();
  6. a.CommonData.RelatedItems.Add(b.CommonData.ClientId);
  7. Call NewItems and pass in both instances

We would likely provide a helper function to do #3 - #6, so you could merely write "MakeThingsRelated(a, b)", and the helper would do all the work of generating the client ids and hooking them up.

We would also modify "GetItem" to retrieve an object either using the Key.Id or the Client id, and the code you would write to fetch the related items would be the same as what you currently write.

There are three disadvantages to this approach that we see:

  1. The client id isn't invariant, so it's possible for me to set up a related item and then have another app come along and change the client id, breaking the related item. However, apps can already delete the related item or remove an entry from the related item list, so I don't think it's really any different than our current behavior.
  2. GetItem() currently takes a instance Id, and in the new world it would take either an instance ID or a client ID. That means that it's a little more confusing to developers to figure out what is going on when they look at code.
  3. HealthRecordItemRelationship now holds two different kinds of information, and you have to know which is which. I think that with a bit of encapsulation, we can make the impact of this to be small.

We could avoid #2 and #3 by adding a new method to fetch an item by clientId (ie GetItemByClientId()). That would make that api clearer, but would have the unfortunate byproduct of requiring a rewrite of all existing code that uses related items to be able to deal with client-related items (it would need to know whether to call GetItem() or GetItemByClientId()...).

We're leaning towards doing the client-id approach, but would like any thoughts you might have.