Annoncée la semaine dernière à la BUILD, voici une addition très pratique à l’API des Windows Azure Storage Tables. Le problème adressé est le suivant: avant cette fonctionnalité, il n’était tout simplement pas possible d’envoyer une mise à jour de type “update or insert”, c’est-à-dire d’envoyer une liste d’entités et de demander au Storage de faire le tri entre les entités qui sont nouvelles (à insérer) et celles qui existent déjà (à mettre à jour). Il fallait faire l’opération en deux fois, après avoir déterminé soi-même quelles entités étaient nouvelles, et lesquelles étaient mises à jour.

La capture ci-dessous expose le problème: (cliquez sur l’image pour la voir en taille originale)

image

L’on voit que j’itère ici sur un tableau d’objets, et que j’utilise un TableServiceContext pour les référencer et les sauver dans le Table Storage. Il se trouve que j’utilise également la possibilité de batcher ces mises à jour, par paquets de 100 maximum.

L’exception vient du fait que dans mon tableau, certaines entités existent déjà; voici le détail de l’exception:

image

La nouvelle fonctionnalité Upsert permet de réaliser cette même opération en changeant légèrement la syntaxe:

var context = new TableServiceContextV2(tableClient.BaseUri.ToString(), tableClient.Credentials);
var n = 0;
foreach (var k in FriendLikes.Keys)
{
	context.AttachTo(FRIEND_LIKES_TABLE, FriendLikes[k]);
	context.UpdateObject(FriendLikes[k]);
	if (n++ % 100 == 0)
	{
		context.SaveChangesWithRetries(SaveChangesOptions.Batch|SaveChangesOptions.ReplaceOnUpdate);
	}
}

Voici les modifications:

  • J’utilise un nouveau TableServiceContext qui permet d’envoyer les en-têtes nécessaires pour que le Storage reconnaisse cette nouvelle API (voir ci-dessous)
  • Au lieu de faire un AddObject(), je fais un AttachTo() suivi d’un UpdateObject()
  • J’ajoute un SaveChangesOptions.ReplaceOnUpdate qui indique que je veux remplacer toute l’entité si elle existe déjà (par défaut, un Merge serait effectué)

La nouvelle classe TableServiceContextV2 nous est fournie dans le billet de l’équipe Windows Azure Storage:

public class TableServiceContextV2 : TableServiceContext
{
	private const string StorageVersionHeader = "x-ms-version";
	private const string August2011Version = "2011-08-18";
	public TableServiceContextV2(string baseAddress, StorageCredentials credentials) :
		base(baseAddress, credentials)
	{
		this.SendingRequest += SendingRequestWithNewVersion;
	}
	private void SendingRequestWithNewVersion(object sender, SendingRequestEventArgs e)
	{
		HttpWebRequest request = e.Request as HttpWebRequest;
		// Apply the new storage version as a header value
		request.Headers[StorageVersionHeader] = August2011Version;
	}
}

Cette nouvelle classe ajoute à la volée un en-tête HTTP précisant le nouveau numéro de version de l’API. Cela permet à votre application de bénéficier des nouvelles fonctionnalités, alors que les applications utilisant le précédent numéro de version d’API continuent de voir le fonctionnement habituel.

Une précision importante cependant: cette nouvelle version d’API est uniquement implémentée dans la fabrique de production Windows Azure, et pas dans l’émulateur local! Il vous faudra donc vous connecter à un “vrai” compte de Storage pour tester cette nouvelle fonctionnalité.

Cette nouvelle API simplifie énormément l’utilisation des Tables dans certains scénarios.