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 :
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 :
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 :
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à :
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 :
[EnableClientAccess()]
public
class
SuperEmployeeDomainService :
LinqToSuperEmployeeDomainService
{
public
IQueryable<
SuperEmployee>
GetSuperEmployees
(
)
{
return
this
.
Context;
}
Et le code de votre DomainService personnalisé ? Assez facile aussi.
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 de nous avoir autorisés à traduire son article.
Je remercie également ClaudeLELOUP et jacques_jean pour leur relecture et leurs propositions.