Traduction

Cet article est la traduction la plus fidèle possible de l'article original de Brad Abrams, Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 18: Custom Linq Provider.

Article

On continue notre discussion sur Silverlight 3 et la mise à jour de .NET RIA Services. J'ai mis à jour l'exemple de ma présentation du Mix09 "Building business applications with Silverlight 3". RIA Services est essentiellement une extension du projet LINQ. Vous pouvez effectivement voir RIA Services comme du LINQ en n-tiers. À ce titre, j'ai pensé qu'il serait intéressant de montrer comment n'importe lequel des nombreux providers Linq peut être utilisé avec RIA Services.

Vous pouvez regarder la vidéo originale de la session complète.

Cette démo nécessite les éléments suivants (tout est 100 % gratuit) :

  • Visual Studio 2008 SP1 (qui inclut SQL Server Express 2008) ;
  • Silverlight 3 RTM ;
  • .NET RIA Services July '09 Preview.

Téléchargez aussi les fichiers de la démo complète, et jetez un œil à l'application en cours d'exécution.

Voici la structure générale de l'application que nous allons étudier cette fois :

Image non disponible

Dans la partie 8 (WCF), j'avais présenté comment obtenir vos données à partir d'un service WCF (plutôt qu'à partir d'Entity Framework) via RIA Services. Une chose dont je n'étais pas vraiment content était qu'il fallait passer le numéro de page dans la méthode de requête. Bien que David Poll et moi-même ayons développé un petit système de pagination sympa qui fonctionnait avec ça, on trouvait que ça ressemblait vraiment à du bricolage... et Jason Allor, notre manager de développement, était tout à fait du même avis. Le cœur du problème était que je n'avais pas de IQueryable connaissant mes services WCF à renvoyer . Jason m'a assuré que ce serait facile à faire à partir de l'exemple de fournisseur Linq to TerraServer et de l'excellente série de b de Matt Warrenillets. Je l'ai donc mis au défi d'essayer, et il l'a fait !

Ce à quoi Jason est arrivé est assez cool. Ça ne couvre pas 100 % des cas que RIA Services pourrait utiliser, mais ça en couvre quand même beaucoup, et tout le code source est là, donc n'hésitez pas à l'utiliser et à l'étendre.

Dans mon exemple WCF d'origine, ma méthode de requête ressemblait à ça :

 
Sélectionnez

public IQueryable<SuperEmployee> GetSuperEmployees(int pageNumber)
{
   return this.Context.GetSuperEmployees(pageNumber)
              .Where(emp => emp.Issues > 100)
              .OrderBy(emp => emp.EmployeeID)
              .Select(emp =>
                  new MyApp.Web.SuperEmployee()
                  {
                      EmployeeID = emp.EmployeeID,
                      Gender = emp.Gender,
                      Issues = emp.Issues,
                      LastEdit = emp.LastEdit,
                      Name = emp.Name,
                      Origin = emp.Origin,
                      Publishers = emp.Publishers,
                      Sites = emp.Sites,
                  }).AsQueryable();
}

En gros, le LinqToSuperEmployeeService analyse la requête Linq et nous donne accès aux différentes parties de la requête :

 
Sélectionnez

internal class LinqToSuperEmployeeService : QueryableService<SuperEmployee>
{
   private SuperEmployeeServiceClient context;

   public LinqToSuperEmployeeService(SuperEmployeeServiceClient context)
   {
       this.context = context;
   }

   protected override object ExecuteQuery(QueryDetails details)
   {
       if (details.Count)
       {
           return this.context.GetSuperEmployeesCount(
               details.SkipSize, 
               details.PageSize, 
               details.OrderBy,
               details.Filters.ToArray());
       }
       else
       {
           return this.context.GetSuperEmployees(
               details.SkipSize, 
               details.PageSize, 
               details.OrderBy,
               details.Filters.ToArray())
          .Select(emp => ConvertUtils.Convert(emp));
       }
   }
}

Par exemple, prenez une requête comme celle-là :

 
Sélectionnez

q.Skip(20).Take(10)
 .OrderBy(e => e.Name)
 .Where(e => e.Origin == "Earth");

Cela appellerait en fin de compte GetSuperEmployees(20,10,null,{"Earth"}).

La classe de base QueryableService extrait de la requête les paramètres de pagination et de tri et les met dans la classe QueryDetails. Ensuite, dans la méthode Execute, on récupère ces paramètres et on les passe au service WCF. Vous pourriez tout aussi bien utiliser ces valeurs pour appeler un service REST ou générer du TSQL, etc.

Si vous voulez réutiliser cette fonctionnalité pour votre service WCF, il suffit de créer sa propre classe dérivée de QueryableService et de faire le nécessaire avec les valeurs.

Encore un point sympa, si vous créez votre propre sous-classe de DomainService qui peut gérer l'appel à un service WCF, les choses deviennent encore plus simples :

 
Sélectionnez

[EnableClientAccess()]
 public class SuperEmployeeDomainService : LinqToSuperEmployeeDomainService
 {
    public IQueryable<SuperEmployee> GetSuperEmployees()
    {
        return this.Context;
    }

Et le code de votre DomainService personnalisé ? Assez facile aussi.

 
Sélectionnez

public class LinqToSuperEmployeeDomainService : DomainService
{
   private SuperEmployeeServiceClient webServiceContext = new SuperEmployeeServiceClient();

   private LinqToSuperEmployeeService linqContext;

   protected LinqToSuperEmployeeDomainService()
   {
       this.linqContext = new LinqToSuperEmployeeService(this.webServiceContext);
   }

   public IQueryable<SuperEmployee> Context
   {
       get { return this.linqContext; }
   }

   public SuperEmployeeServiceClient WebServiceContext
   {
       get { return this.webServiceContext; }
   }
}

Cette partie concernait la façon d'utiliser un fournisseur Linq personnalisé facilitant l'appel d'un service WCF pour récupérer des données à partir de votre client Silverlight. Le fournisseur Linq très simple que j'ai montré ici peut facilement être personnalisé pour travailler avec n'importe quel service ou autre source de données.

Conclusion

Ceci conclut la dix-huitième partie de cette série. La partie suivante traitera d'ASP.NET Dynamic Data.

Remerciements

Je tiens ici à remercier Brad Abrams pour nous avoir autorisé à traduire son article.
Je remercie également ClaudeLELOUP et jacques_jean pour leur relecture et leurs propositions.