Projektowanie, Programowanie, Codzienność – BeniaminZaborski.com

28 stycznia 2014

Z LINQ jak po sznurku

Filed under: How Can I Take ... — Tagi: , , , , — Beniamin Zaborski @ 22:56

Każdy programista .NET słyszał, zna i zapewne używa LINQ. To bezsprzecznie świetny mechanizm. Świetny jest do tego stopnia, że teraz to środowisko Java przeszczepia go z .NET do siebie, a nie odwrotnie … ghhh. Sorry Javowcy taki teraz mamy klimat:).

Hola, hola … można by powiedzieć, bo w naszym fajnym LINQ można się rozbić o ścianę! Co gdy chce sobie dynamicznie złożyć zapytanie?

Pokażę to na podstawie trywialnego przykładu. Mamy listę obiektów:

var kontrahenci = new List<Kontrahent>() {
 new Kontrahent { Nazwa = "Kontrahent 1", Symbol="KWA1", CzyAktywny = true },
 new Kontrahent { Nazwa = "Kontrahent 2", Symbol="KSL2", CzyAktywny = false },
 new Kontrahent { Nazwa = "Kontrahent 3", Symbol="KWE2", CzyAktywny = false },
 new Kontrahent { Nazwa = "Kontrahent 4", Symbol="KNO2", CzyAktywny = true }
 };

i chcemy dynamicznie złożyć i wykonać poniższe zapytanie:

kontrahenci.Where(k => k.CzyAktywny && k.Symbol.Contains("2")).ToList();

Jak to zwykle bywa jest parę opcji, np.:

1. Użycie dynamic expressions:

 ParameterExpression kontrahentParam = Expression.Parameter(typeof(Kontrahent), "k");
 Expression leftCzyAktywnyExpression = Expression.Property(kontrahentParam, "CzyAktywny");
 Expression rightCzyAktywnyExpression = Expression.Constant(false);
 Expression czyAktywnyExpression = Expression.Equal(leftCzyAktywnyExpression, rightCzyAktywnyExpression);
 Expression leftSymbolExpression = Expression.Property(kontrahentParam, "Symbol");
 Expression rightSymbolExpression = Expression.Constant("2", typeof(string));
 Expression symbolExpression = Expression.Call(leftSymbolExpression, typeof(string).GetMethod("Contains", new[] { typeof(string) }), rightSymbolExpression);
 Expression andExpression = Expression.AndAlso(czyAktywnyExpression, symbolExpression);
 var whereExpression = Expression.Lambda<Func<Kontrahent, bool>>(andExpression, kontrahentParam).Compile();
 kontrahenci.AsQueryable().Where(whereExpression).ToList();

Wygląda okrutnie, a to przecież banalny przykład. Pomyślcie co się dzieje w tych naprawdę złożonych? Musi boleć.

2. Dynamic Expression API i zapytanie ze stringa:

kontrahenci.AsQueryable().Where("CzyAktywny == @0 and Symbol.Contains(@1)", false, "2").ToList();

Teraz lepiej? No myślę, że zdecydowanie!

A przed tym wszystkim wystarczy tylko:

1. Install-Package DynamicQuery

2. using System.Linq.Dynamic;

Stwórz darmową stronę albo bloga na WordPress.com.