MedTracker - Part 3

Developing NS MedTracker – part 3
Advanced Concepts

by Burag Cetinkaya

In Part 2 of the series, we explored how items are stored in HealthVault, item/account hierarchy, and finally we developed a simple application to store/retrieve Medications from HealthVault using the available SDK. In this part of the series, we will look at more advanced concepts.

Storing user settings for an application in HealthVault

In addition to storing health records that belong to a user, HealthVault also supports applications to store application-related user settings in HealthVault. If you are developing a HealthVault integrated application that uses HealthVault as the only data persistence medium, this feature eliminates the need to have a local database to store user related settings/preferences for your application.

Let's take a look at an example. The MedTracker application that we have been developing, does not support changing the alternating row colors on the Medications page. We can create an application setting to store the alternate color that each user will pick. We can then store this setting in HealthVault, eliminating the need to keep a local database for the purpose of storing settings.

48 var settingsWriter = XmlWriter.Create(stream);

49 settingsWriter.WriteStartElement("app-settings");

50 settingsWriter.WriteStartElement("settings");

51 settingsWriter.WriteElementString("background", BackgroundColor);

52 settingsWriter.WriteEndElement();

53 settingsWriter.WriteEndElement();


One thing to notice in this snippet is the first element. HealthVault requires the first element in an XML settings snippet to be app-settings. The above code creates an XML settings snippet that has the background information we want to store for the currently logged in user.

After storing the settings in HealthVault, the application settings can be read at any time from HealthVault. To minimize the number of calls to Healthvault we store the settings in the session after the first retrieval. Subsequent calls to retrieve the settings are satisfied by using the data in the session instead of calling HealthVault. Keep in mind that the settings need to be extracted from the XML snippet. Here is a code snippet that retrieves the data from HealthVault and extracts the background information that the user previously stored.

47 ApplicationSettings.LoadFromXML(this.PersonInfo.ApplicationSettings);


This in turn extracts the followign information:

30 public static ApplicationSettings LoadFromXML(IXPathNavigable settings)

31 {

32 if (settings == null)

33 return ApplicationSettings.CreateDefaultApplicationSettings();

34 var navigator = settings.CreateNavigator();

35 var bgNode = navigator.SelectSingleNode("/app-settings/settings/background");


Relationships between records stored in HealthVault

In Part 2 of the series we looked at how records are stored in HealthVault. Each type is stored separately and can be retrieved by issuing a query. However, there might be some cases where an application might want to link correlated records. HealthVault provides such a facility through the HealthRecordItemRelationship type. Each type, such as Medication, Blood Pressure, etc., has a RelatedItems property that can be queried in order to retrieve the IDs of related items. An application can then extract these IDs and perform the necessary retrieval if needed. Keep in mind that the relationships are rather soft links and are not enforced in HealthVault. These links should not be treated as the foreign key constraints that we all are used to from the relational database world.

Here is a code snippet that will check if the medication has been prescribed by a certain physician. If a related physician contact is found, it will then query HealthVault to get the contact information. Note that this is not the optimal way of doing this. It’s for illustration purposes only, and the current demo does not utilize this functionality.

153 private bool TryExtractPhysicianContactInformation(Medication medication, out string physicianContactInformation)

154 {

155 if (medication == null)

156 throw new ArgumentNullException("medication");

157 if (medication.CommonData.RelatedItems != null || medication.CommonData.RelatedItems.Count > 0)

158 {

159 var physicianRelationships = (from r in medication.CommonData.RelatedItems

160 where r.RelationshipType == "Physician"

161 select r).ToList();

162 if (physicianRelationships.Count == 0)

163 return false;

164 return GetPhysicianContactInformation(physicianRelationships[0].ItemKey.Id);

165 }

166 }


Each relationship contains two properties: the RelationshipType and the ItemKey of the related item. In the above example we query all the relationships based on the RelationshipType property. Extract all the physicians and return the contact information of the first physician in the related items list.

This could be an interesting way to keep correlations in HealthVault, for example Medications can be linked to certain vital sign measurements based on the fill date. This could end up in an object graph that can be traversed based on just one piece of information. In particular, health dashboards could utilize this feature to come up with interesting visual representations for related health records.

Returning multiple result sets with one query

In Part 2 of the series we explored how to query HealthVault to return medication records for a user. By that model, we would have to call HealthVault N times to retrieve N different item types such as Medications, Procedures, etc. Fortunately, HealthVault allows sending multiple filters on a searcher object. This in return translates into multiple resultsets. For example, the snippet below will return all the Medications and Procedures that belong to a user in one call:

86 var searcher = this.PersonInfo.SelectedRecord.CreateSearcher();

87 var medicationFilter = new HealthRecordFilter();

88 medicationFilter.TypeIds.Add(Medication.TypeId);

89 var procedureFilter = new HealthRecordFilter();

90 procedureFilter.TypeIds.Add(Procedure.TypeId);

91 searcher.Filters.Add(medicationFilter); // 0 - Medications

92 searcher.Filters.Add(procedureFilter); // 1 - Procedures

93

94 var resultSets = searcher.GetMatchingItems(); // Contains both collections.

95 var medications = resultSets[0];

96 var procedures = resultSets[1];


Things to consider

Although we have covered the basics of HealthVault interaction there are some major items to consider when integrating your application with HealthVault. I will list some of the major pain points in integration:

  • Unit of Measure Conversions: With multiple suppliers of data into a central repository comes the question on unit standardization. Your application might need to do some conversions before it can process the data that comes from HealthVault.
  • Data Mapping and Translation: Existing applications work with schemas that have evolved over time to accommodate the business’ needs. There might not be an option for changing the internal schemas to conform to HealthVault type schemas. Additional mapping and transformation might be needed when converting local application types to HealthVault types and vice versa.
  • Querying data: HealthVault provides search filters to query data. Advanced filters, however, require some knowledge about the internal representation of the type in order to craft the required XPath queries. This can be a major pain point for some applications that need to perform complex queries.

Please check out the HealthVault Connector, which addresses most of the aforementioned problems in HealthVault integration with minimal change in your existing application.

Download the source code for the article series.


Send your comments to insights@netsoft-usa.com.