Charger une association dans WCF RIA Services

Je l’avais annoncé ici : .NET RIA services est devenu WCF RIA Services.

Rappels

L’objectif de ce projet est de simplifier le développement d’applications RIA.

Le principe général est assez simple :
Je développe des services de domaine (CRUD + Queries) en utilisant des conventions de nommage côté serveur.

Par exemple, la méthode Sprint LoadSprint(int sprintId) renvoie un sprint d’une application Scrum à partir de son identifiant.

WCF RIA Services projette ce code côté client dans des classes de type DomainContext.

Dans notre exemple, j’obtiens une classe ScrumDomainContext avec une méthode EntityQuery<Sprint> LoadSprintQuery(int sprintId)

Projection de code
Projection de code

Les associations

La version beta est disponible depuis le mois de Novembre. On trouve sur le Web quelques introductions, notamment celles de Brad Abrams. En revanche, on trouve très peu de choses sur comment charger une association dans notre application cliente Silverlight.

Dans mon exemple, je veux afficher une vue Master/Details qui présente un sprint et la liste de ses tâches.

Le modèle

Sprint association
Sprint association

La déclaration de l’association

Je dois ensuite décrire à WCF Ria services les associations entre mes entités. Pour cela, je décore les propriétés Tasks de la classe Sprint, et Sprint de la classe Task avec l’annotation AssociationAttribute. Il faut indiquer un nom pour cette association, par exemple Sprint_Tasks et préciser les clés étrangères de chacune de ses relations. Dans le sens Sprint -> Task, la clé c’est le champ Id de la classe Sprint et la clé étrangère c’est le champ SprintId de la classe Task.


public class Sprint{
[Key]
public virtual int Id { get; set; }

[Association(« Sprint_Task », « Id », « SprintId »)]
public virtual ICollection Tasks { get; set; }
}

Quelques remarques :

  1. Les habitués de NHibernate vont déplorer le fait d’avoir à décrire l’association à l’aide des clés étrangères. Cela nécessite par ailleurs d’avoir une propriété SprintId dans la classe Task en plus de la propriété Sprint 🙁
  2. La décoration est automatique avec l’utilisation de LinqToSql ou d’Entities Framework

Le chargement explicite

Il reste enfin à indiquer explicitement que l’on souhaite sérialiser les tâches avec le sprint. Pour cela, nous devons définir une classe de méta données relative à la classe métier. Dans notre exemple, ce sera une classe SprintMetaData définissant un champ Tasks que l’on décore avec l’annotation IncludeAttribute.


public class SprintMetaData {
[Include]
public EntitySet Tasks;
}

Je vous laisse regarder le blog de Brad Adams ou un ancien billet pour les détails de la classe de méta données.

Personnellement je trouve dommage d’avoir à définir une stratégie de chargement dans un fichier de méta données. L’idée générale n’est pas mauvaise, mais présente un inconvénient majeur : la stratégie est valable pour tous les cas d’utilisation. Or il est probable que l’application ne nécessite à la fois le sprint et ses tâches que dans certains écrans …

Outils de mapping objet/relationnel

Si vous utilisez un ORM, n’oubliez pas de récupérer la collection de tâches dans votre requête.

Avec LinqToEntities, ça donne :


public Sprint LoadSprint(int sprintId){
return this.Context.Sprints
.Include("Tasks")
.Where(sprint=>sprint.Id == sprintId);
}

Avec LinqToNhibernate, ça donne:


public Sprint LoadSprint(int sprintId)
{
var result = this.Session.Linq().Expand("Tasks")
.Where(x => x.Id == sprintId)
.ToList().First();
return result;
}

Conclusion

Nous avons vu en détail comment charger une association entre deux entités dans une application WCF Ria Services. Une partie de ces détails est masquée par l’outillage fourni par Microsoft et nous ferait presque oublier la complexité qui ne manquera pas de ressortir si vous souhaitez utiliser cette pile en association avec des outils tel que NHibernate

Publier un service en .NET

Si vous avez suivi mes billets sur le sujet, vous devez probablement vous demander quelle pile utiliser pour exposer un service en .NET: WCF ? .NET Ria services ? ADO.NET Data Services ?

Et bien Microsoft va unifier ces piles dans le framework 4 en proposant des extensions de WCF. Au passage, un renommage s’impose :

  • ADO.NET Data Services (anciennement Astoria) devient WCF Data Services
  • .NET RIA Services devient WCF RIA Services

Voici l’annonce de Mike Flasko.