2008-09-22 9 views
14

Wraz z wprowadzeniem interfejsu .NET 3.5 i IQueryable<T> pojawią się nowe wzory. Chociaż widziałem wiele implementacji wzoru specyfikacji, nie widziałem wielu innych wzorców z wykorzystaniem tej technologii. Aplikacja Rob Consta's Storefront to kolejny konkretny przykład z użyciem IQueryable<T>, który może prowadzić do nowych wzorów.Wzorce projektowe przy użyciu IQueryable <T>

Jakie wzory wyłoniły się z użytecznego interfejsu IQueryable<T>?

Odpowiedz

8

Z pewnością znacznie uprościł również sposób tworzenia repozytorium. Można w zasadzie utworzyć rodzajowe repozytorium

public class LinqToSqlRepository : IRepository 
{ 
    private readonly DataContext _context; 

    public LinqToSqlRepository(DataContext context) 
    { 
     _context = context; 
    } 

    public IQueryable<T> Find<T>() 
    { 
     return _dataContext.GetTable<T>(); // linq 2 sql 
    } 

    /** snip: Insert, Update etc.. **/ 
} 

a następnie używać go z LINQ:

var query = from customers in _repository.Find<Customer>() 
      select customers; 
7

Lubię wzorzec repozytorium filtr. Umożliwia oddzielenie problemów od środkowej i końcowej warstwy danych bez obniżania wydajności.

Twój warstwa danych może skoncentrować się na prosty list-get-zaoszczędzić operacje stylu, w czasie, gdy warstwa środkowa może wykorzystać rozszerzenia IQueryable, aby zapewnić bardziej niezawodne działanie:

repozytorium (warstwa danych):

public class ThingRepository : IThingRepository 
{ 
    public IQueryable<Thing> GetThings() 
    { 
     return from m in context.Things 
       select m; // Really simple! 
    } 
} 

Filter (warstwa 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; 
    } 
} 

Usługa:

public GetThingsForUserID(int userID) 
{ 
    return repository.GetThings().ForUserID(userID); 
} 

Jest to prosty przykład, ale filtry można bezpiecznie łączyć w celu tworzenia bardziej skomplikowanych zapytań. Wydajność zostanie zapisana, ponieważ lista nie zostanie zmaterializowana, dopóki wszystkie filtry nie zostaną wbudowane w zapytanie.

Uwielbiam, bo nie lubię repozytoriów aplikacji!

+0

Co z filtrami krzyżowymi? Mam na myśli, co jeśli chcesz coś takiego 'code' IQueryable things2 = repo.GetThings(). ForUserId (userId) .GetSubthings()' code'? Czy zrobiłbyś GetSubthings() coś takiego: 'code'GetSubThings (this IQueryable things, IQueryable subthings) {}' code'? – mayu

+0

Nie, chciałbym utworzyć drugą klasę rozszerzenia dla 'IQueryable ', nazwać ją 'HavingStatus()', która byłaby dostępna dla rzeczy takich jak 'GetThings(). ForUserId (userId) .Subthings.HavingStatus (status)' ... Ponieważ jeśli Thing jest LinqToSql, to już definiuje 'Subthings', więc nie potrzebujesz klasy rozszerzenia' GetSubthings() ' –

Powiązane problemy