J'aime le modèle référentiel-filtre. Il vous permet de séparer les problèmes du niveau intermédiaire et de fin de données sans sacrifier les performances.
Votre couche de données peut se concentrer sur les opérations simples de style liste-get-save, alors que votre niveau intermédiaire peut utiliser des extensions à IQueryable pour fournir des fonctionnalités plus robustes:
dépôt (couche de données):
public class ThingRepository : IThingRepository
{
public IQueryable<Thing> GetThings()
{
return from m in context.Things
select m; // Really simple!
}
}
filtre (couche de service):
public static class ServiceExtensions
{
public static IQueryable<Thing> ForUserID(this IQueryable<Thing> qry, int userID)
{
return from a in qry
where a.UserID == userID
select a;
}
}
service:
public GetThingsForUserID(int userID)
{
return repository.GetThings().ForUserID(userID);
}
Ceci est un exemple simple, mais les filtres peuvent être combinés en toute sécurité pour générer des requêtes plus complexes. Les performances sont enregistrées car la liste n'est matérialisée que lorsque tous les filtres ont été intégrés dans la requête. Je l'aime parce que je n'aime pas les dépôts spécifiques à l'application!
Qu'en est-il des filtres de type croisé? Je veux dire, que faire si vous voulez quelque chose comme 'code' IQueryable choses2 = repo.GetThings(). ForUserId (userId) .GetSubthings()' code'? Souhaitez-vous faire GetSubthings() quelque chose comme ceci: 'code'GetSubThings (ce IQueryable choses, IQueryable sous-titres) {}' code'? –
mayu
Non, je voudrais créer une deuxième classe d'extension pour 'IQueryable', appelez-la 'HavingStatus()' qui serait disponible pour des choses comme 'GetThings(). ForUserId (userId) .Subthings.HavingStatus (status)' ... Parce que si Thing est LinqToSql, il définit déjà 'Subthings' de sorte que vous n'avez pas besoin d'une classe d'extension' GetSubthings() ' –