mars
2010
Bonjour à vous ! Un petit post mignon tout plein aujourd’hui.
WCF RIA Services nous permet de requêter, de façon quasi transparente, une source de données depuis une application cliente Silverlight (par exemple).
La syntaxe utilisée consiste à appeler Load de l’objet DomainContext instancié et de lui préciser quelle query utiliser.
Ce mécanisme suffit largement pour des filtrages basiques.
Lorsque l’on a à utiliser des filtrage plus complexes, RIA se trouve vite à bout de souffle.
Pour les exemples ci dessous, nous considérons que nous disposons du modèle de données suivant (Entity Framework par exemple) :
Une voiture contient 0-n roues,
Les roues ne sont pas retournées par défaut avec les voitures sur le client (via RIA).
Exemple de situation complexe :
1: var monDomainCtx = new VehiculeDomainSrv();
2: var query = monDomainCtx.GetVoitureQuery().Where(
3: voiture => voiture.Roues.Any(roue=>roue.IsAPlat));
4:
5: monDomainCtx.Load<Voiture>(
6: query,
7: loadOp=>
8: {
9: ... // opération de chargement des voitures à pneu plat
10: },
11: false);
Nous tentons ici (côté client), de demander à RIA d’aller rechercher toutes les voiture qui ont (au moins) un pneu crevé (sous requête).
Dans ce cas de figure (présence d’une ou plusieurs sous requête), RIA va nous renvoyer une exception dont le message parlera d’une impossibilité d’utiliser Any (mais ce serait la même chose pour Count, First, etc).
La solution :
Dans le DomainServices (donc sur le serveur), nous allons implémenter une méthode décorée de l’attribut « System.Web.DomainServices.QueryAttribute ». Nous implémentons donc nos propres query !
Cette méthode retournera donc un objet IQueryable (au même titre que celles fournies par défaut : GetVoitureQuery() )
1: [Query()]
2: public IQueryable<Voiture> GetFiltreVoitures(Boolean roueCrevee)
3: {
4: // création de la query de base retournéà partir du DataModel
5: var dataCtx = new GarageLocationDataModel();
6:
7: return dataCtx.Voiture.Where(voit => voit.Roue.Any(roue => roue.IsAPlat));
8: }
Lors de l’exécution, nous utiliserons le code suivant (côté client)
1: var dataCtx = new VehiculeDomainSrv();
2:
3: dataCtx.Load<Vehicule>(
4: dataCtx.GetFiltreVoiture(true),
5: loadOp=>
6: {
7: // Corps de méthode pour récupérer les résultats
8: ...
9: },
10: false);
Le client ne fait que demander l’exécution de la query, cette dernière sera bien entendu exécutée (physiquement) sur le serveur.
Petite précision sur les méthodes Query :
Il faut noter une petite restriction concernant les paramètres des query : il n’est pas possible (à ce jour) de passer en paramètre un objet d’un type qui encapsule tous les critères de recherche (exemple : CritereVehicule).
En effet, les seuls types autorisés par RIA comme paramètre de query sont les classes qui héritent d’EntityObject et les types simples.
Nous sommes donc “forcés” de lier les couches fortement (pour le moment).