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!
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
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() ' –