LINQ tworzenie warunku w locie

0

Mam następujący problem.

Mam tabelę w MsSQL : samochody -> int id , string nazwa, string marka

Chcę zrobić wyszukiwarkę po marce oraz nazwie tzn gdy użytkownik wpisze nazwe lub/i markę to wyszuka mi samochody spełniące podane warunki.

Zrobiłem to w za pomocą SQLa ale teraz chcę napisać to zapytanie w LINQ.
Normalnie metoda by wyglądała tak:

string warunek = "WHERE "

if(uzytkownikPodalNazwe)
{
   warunek += " nazwa= " + podanaNazwa; 
}

if(uzytkownikPodalMarke)
{
   warunek += " marka = " + podanaMarka; 
}

Wtedy zapytanie wygląda

"SELECT nazwa, marka FROM samochody " + warunek;

W Powyższym przykładzie pominąłem kilka rzeczy które jeszcze trzeba by sprawdzić ( np usunąć where jeśli nie podał ani marki ani nazwy ) ale ogólna idea jest taka, że tworzymy warunek do zapytania w locie w zależności od tego co podał użytkownik. Wtedy wygenerowany warunek używamy w zapytaniu, i do bazy odwołujemy się tylko raz z przygotwanym wcześniej zapytaniem.

Teraz jak uzyskać coś takiego w LinQ ?

Można by tak:

var samochody1 = from s1 in _db.samochody
   where s1.nazwa == podanaNazwa
    select s1;

var samochody2 = from s2 in _db.samochody
   where s2.marka == podanaMarka
    select s2;


Samochod[] s = cześćWspólna(samochody1.ToArray<Samochod>(), samochody2.ToArray<Samochod>())

Czyli 2 zapytania do bazy a potem robię część wspólną z 2 tablic.
Idea jest ładna bo można ją łatwo rozszerzyć o nowe warunki ( np później chcę wyszukiwać po dacie która będzie większa/równa/mniejsza od podanej ) Ale...

..Ale jak widać to nie jest efektywne bo 2 razy wykonujemy zapytanie do bazy danych. Przy większej ilośći parametrów czas otrzymania odpowiedzi by był pewnie znacznie dłuższy.
Czyli tutaj znowu chciałbym wygenerować zapytanie w locie, w zależności od tego co podał użytkownik(i czy w ogóle coś podał )tak aby tylko jednorazowo odwołać się do bazy.

Czy ma ktoś może jakiś pomysł?
pzdr

0

Zapytanie LINQu nie wykonuje się bezpośrednio w linijce:

var samochody1 = from s1 in _db.samochody
   where s1.nazwa == podanaNazwa
    select s1;

czy też:

var samochody2 = from s2 in _db.samochody
   where s2.marka == podanaMarka
    select s2

;

dopóki nie skorzystasz z jakiejś metody np. ToList czy ToArray, czy też nie użyjesz foreach do wyświetlenia wyniku zapytanie się nie wykona.
Dlatego można w łatwy sposób budować dynamiczne zapytanie. W Twoim przypadku może coś takiego będzie dobre:

//Tutaj jeszcze zapytanie nie zostanie wyslane do bazy danych
var samochody1 = from s1 in _db.samochody
   where s1.nazwa == podanaNazwa
    select s1;

//Wywolujac metode ToArray nasze zapytanie wyciagnie dane z bazy i zapisze je do tablicy
var samochody2 = (from s2 in samochody1 
   where s2.marka == podanaMarka
    select s2).ToArray<Samochod>();

Mam nadzieję że w miarę zrozumiale to wytłumaczyłem. Jak coś niejasne - pisz.

Pozdrawiam

0

mozesz tez w ten sposob dolaczac kolejne warunki, a linq to sql bedzie umial w jedno query to zlozyc

var q = from sl in _db.samochody
select sl;

if (!string.IsNullOrEmpty(podanaMarka))
q = q.Where(x=>x.marka == podanaMarka);

if (!string.IsNullOrEmpty(podanaNazwa))
q = q.Where(x=>x.marka == podanaNazwa);

var list = q.ToList(); // dopiero w tym momencie wykonywane jest zapytanie do bazy danych

0

Dziękuje Wam za odpowiedzi!
Dokładnie takich informacji mi brakowało :)

pzdr!

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