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;