Merge kilku IQueryable

0

Hej, chciałbym połączyć kilka IQueryable w jeden. Znalazłem metodę .Concat(), która wydaje mi się być dobra, ale może w zły sposób ją wykorzystuję. Mam mniej więcej taki kod:

             if (Status.Contains(R))
            {
                 pF = q.Where(a => a.ADP && a.Status.Equals(R));
            }

            if (Status.Contains(NC))
            {
                pF = q.Where(a => a.ADP && a.Status.Equals(NC));
            }

            if (Status.Contains(E))
            {
                pF = q.Where(a => a.ADP && a.Status.Equals(E)));
            }

Każdy z powyższych ifów zwraca IQueryable i teraz chciałbym je połączyć w jakiś jeden nadrzędny, który mógłbym zwrócić w returnie, który zawierałby w sobie wszystkie składowe. W jaki sposób można by to zgrabnie zrobić?

2

zamiast pF daj q

0

To wtedy będę miał zwrotkę z jednego ifa który się wywoła. Tu chodzi wlasnie o to ze raz funkcja wejdzie w jednego ifa, kolejny raz w dwa lub trzy. Dlatego chciałbym jakos merdzowac otrzymane wyniki.

0

Chcesz zrobić ANDy na tych predykatach czy OR?

Mają być wszystkie warunki spełnione, czy wszystkie dane spełniające którykolwiek z warunków?

0

ANDy. Wszystkie spełnione. Tzn może być spełniony jeden, dwa lub trzy i w zależności od tego chciałbym mieć wszystkie wyniki

2

No to tak jak pisałem powinno zadziałać

IQueryable<Uzyszkodnik> query = database.Users;

if (a > 5)
{
	query = query.Where(x => x.Age > 5);
}

if (imie == "tomek")
{
	query = query.Where(x => x.Imie == imie);
}

var result = await query.ToListAsync();

I jeżeli a > 5 oraz imie == tomek, to oba te warunki będą dodane do tego query.
Jeżeli tylko age > 5, to tylko x.Age > 5

Po prostu przy każdym if dokładasz kolejny Where do tego całego LINQ Chaina, a na końcu następuje evaluation/materializacja.

0
WeiXiao napisał(a):

No to tak jak pisałem powinno zadziałać

IQueryable<Uzyszkodnik> query = database.Users;

if (a > 5)
{
	query = query.Where(x => x.Age > 5);
}

if (imie == "tomek")
{
	query = query.Where(x => x.Imie == imie);
}

var result = await query.ToListAsync();

I jeżeli a > 5 oraz imie == tomek, to oba te warunki będą dodane do tego query.
Jeżeli tylko age > 5, to tylko x.Age > 5

Po prostu przy każdym if dokładasz kolejny Where do tego całego LINQ Chaina, a na końcu następuje evaluation/materializacja.

Hm no nie wiem dlaczego ale nie działa mi to. Co prawda nie robię na końcu tego awaita - jest on tam konieczny? A jeżeli jest to jak zwrócić to nadal jako IQueryable a nie listę?

0

Czy chodzi o coś takiego?

            var pF = Enumerable.Empty<TWOJ TYP>();

            if (Status.Contains(R))
            {
                 pF = pF.Concat(
                     q.Where(a => a.ADP && a.Status.Equals(R)));
            }

            if (Status.Contains(NC))
            {
                pF = pF.Concat(
                    q.Where(a => a.ADP && a.Status.Equals(NC)));
            }

            if (Status.Contains(E))
            {
                pF = pF.Concat(
                    q.Where(a => a.ADP && a.Status.Equals(E)));
            }
0

Myślę że na początku OP musi ustalić czy chce przecięcie (cond1 AND cond2 AND cond3) czy unię (cond1 OR cond2 OR cond3). Ułatwi to zadaniem nam wszystkim. W przypadku wyszukiwania polecam przecięcie - jak szukam mieszkania po liczbie pokoi i cenie to chcę żeby spełnione były oba warunki (cena taka a taka i 3 pokoje).

Zamiast łączyć IQueryable jak sugerują powyższe odpowiedzi możesz też łączyć Expression'ny. Potem takie połączone Expression przekazujesz normalnie do IQueryable.Where(expr) - taki poor man specification pattern z tego wychodzi: https://enterprisecraftsmanship.com/posts/specification-pattern-c-implementation/

Jak połączyć expressiony: https://stackoverflow.com/a/20465785

Pamiętaj że żeby kompilator skonwertował lambdę na expression musisz jawnie podać typ zmiennej:
Expression<Func<T, bool>> f = x => x.Age > 5;

Z var
var f = x => x.Age > 5;
nie zadziała.

1 użytkowników online, w tym zalogowanych: 0, gości: 1