me gusta el patrón repositorio-filtro. Le permite separar las preocupaciones del nivel medio y final de datos sin sacrificar el rendimiento.
Su capa de datos se puede concentrar en una simple lista-conseguir-ahorrar operaciones de estilo, mientras que su nivel medio puede utilizar extensiones a IQueryable para proporcionar una funcionalidad más robusta:
Repositorio (capa de datos):
public class ThingRepository : IThingRepository
{
public IQueryable<Thing> GetThings()
{
return from m in context.Things
select m; // Really simple!
}
}
filtro (capa de Servicio):
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;
}
}
Servicio:
public GetThingsForUserID(int userID)
{
return repository.GetThings().ForUserID(userID);
}
Este es un ejemplo simple, pero los filtros se pueden combinar de forma segura para crear consultas más complicadas. El rendimiento se guarda porque la lista no se materializa hasta que todos los filtros se hayan incorporado a la consulta.
¡Me encanta porque no me gustan los repositorios específicos de aplicaciones!
¿Qué pasa con los filtros de tipo cruzado? Quiero decir, ¿y si quieres algo como 'código' IQueryable cosas2 = repo.GetThings(). ForUserId (userId) .GetSubthings()' code'? ¿Haría GetSubthings() algo como esto: 'code'GetSubThings (esto IQueryable cosas, IQueryable subthings) {}' code'? –
mayu
No, crearía una segunda clase de extensión para 'IQueryable', llámala 'HavingStatus()' que estaría disponible para cosas como 'GetThings(). ForUserId (userId) .Subthings.HavingStatus (status)' ... . Porque si Thing es LinqToSql, ya define 'Subthings', por lo que no necesita una clase de extensión' GetSubthings() ' –