2012-02-03 8 views
10

Tôi đang sử dụng LINQ cho các thực thể (EF). Tôi có một hàm tạo có 4 tham số chuỗi. Tùy thuộc vào tham số nào không null Tôi phải xây dựng truy vấn LINQ. Tôi có thể làm với các câu lệnh if else nhưng tôi cũng có hàm tạo khác với 10 tham số trong trường hợp đó sẽ có nhiều kết hợp để kiểm tra.Điều khoản động trong LINQ đối với các thực thể

Ví dụ:

Constructor(p1,p2,p3,p4) 
{ 
    var prod= from p in ctxt.products.expand("items\details") 
      where p.x==p1 && p.xx==p2 && p.xxx==p3 && p.xxxx==p4 
      select p; 
} 

Ở phía trên mệnh đề where cần có kiểm tra điều kiện chỉ nếu tham số là không null. tức., nếu p2 là null thì mệnh đề where nên trông giống như

where p.x==p1 && p.xxx==p3 && p.xxxx==p4 

nếu p2 và p3 là null thì

where p.x==p1 && p.xxxx==p4 

bất cứ ai có thể cho tôi biết làm thế nào để xử lý việc này. nếu có thể bạn có thể cho mẫu mã cho điều này

+0

có thể trùng lặp của http://stackoverflow.com/questions/697345/linq-to-sql- need-dynamic-where-clause-over-relational-tables-help? rq = 1 –

Trả lời

11

DeferredExecution của LINQ để giải cứu. Truy vấn LINQ không được thực hiện trừ khi dữ liệu được yêu cầu từ nó.

var prod = from p in ctxt.products.expand("items\details") 
     select p; 

if (p1 != null) 
{ 
    prod = prod.Where(p => p.x == p1); 
} 

if (p2 != null) 
{ 
    prod = prod.Where(p => p.xx == p2); 
} 

// Execute the query 

var prodResult = prod.ToList(); 
+0

nếu chúng tôi làm như vậy, chúng tôi sẽ tải lượng lớn dữ liệu trong sản phẩm và sau đó chúng tôi đang dùng tập hợp con của nó. Chúng ta có thể nhận được tập con trực tiếp không. – Deepak

+3

Truy vấn là ** NOT ** được thực thi cho đến sau khi mệnh đề where được xây dựng. Inn mã trên truy vấn được xây dựng cho đến khi dòng cuối cùng và đó là nơi nó được thực hiện. Bạn có thể ch3eck này bằng cách chạy SQL profiler. –

+0

Có bạn là chính xác. Tôi có thể sử dụng mã của bạn và nó hoạt động hoàn hảo. – Deepak

3

Bạn có thể chuỗi các phương pháp khi cần thiết:

YourType(string p1, string p2, string p3, string p4) 
{ 
     var prod = ctxt.Products.Expand("items\details"); 

     if (!p1.IsNullOrWhiteSpace()) 
      prod = prod.Where(p => p.x == p1); 
     if (!p2.IsNullOrWhiteSpace()) 
      prod = prod.Where(p => p.xx == p2); 

     // .... 

     // use "prod" 
} 

Các SQL kết quả nên được giống như nếu bạn đặt tất cả chúng trong một tuyên bố duy nhất.

+1

nếu chúng ta làm như thế này, chúng ta sẽ tải lượng lớn dữ liệu trong sản phẩm và sau đó chúng ta đang dùng tập con của nó. Chúng tôi có thể nhận được tập hợp con trực tiếp nếu không chúng tôi đang tải dữ liệu không cần thiết – Deepak

+1

@Deepak Không, bạn sẽ không. Điều tốt đẹp về IQueryable là nó không "tải dữ liệu" - LINQ sử dụng thực thi hoãn lại, và với EF, nó dịch "truy vấn" cuối cùng thành một câu lệnh SQL đơn. Đây sẽ là kết quả tương tự. –

+1

@Deepak Để biết chi tiết, hãy xem: http://stackoverflow.com/questions/1578778/using-iqueryable-with-linq/1578977#1578977 –

2

Bạn luôn có thể xây dựng các truy vấn trong miếng và tận dụng lợi thế của thực hiện truy vấn chậm:

public Constructor(int? p1, int? p2, int? p3, int? p4) 
{ 
    var prod = ctxt.products.expand("items\details"); 

    if(p1 != null) 
     prod = prod.Where(p.x == p1); 

    if(p2 != null) 
     prod = prod.Where(p.xx == p2); 

    if(p3 != null) 
     prod = prod.Where(p.xxx == p3); 

    if(p4 != null) 
     prod = prod.Where(p.xxxx == p4); 
} 
+0

nếu chúng tôi làm như thế này, chúng tôi sẽ tải lượng lớn dữ liệu trong sản xuất và sau đó chúng tôi đang dùng tập con của nó. Chúng tôi có thể lấy tập hợp con trực tiếp nếu không chúng tôi đang tải dữ liệu không cần thiết – Deepak

+1

@Deepak - Bạn sẽ không tải bất kỳ dữ liệu nào cả. LINQ không thực hiện truy vấn cho đến khi bạn thực sự sử dụng dữ liệu. Vào thời điểm truy vấn thực hiện, bạn đã có đúng các điều khoản tại chỗ để chỉ tải dữ liệu bạn cần. –