2011-11-17 34 views
5

Tôi đang làm việc trên một ứng dụng lớn đang sử dụng Dynamic LINQ Library để lọc.Lọc trên truy vấn con bằng cách sử dụng Dynamic LINQ

Tất cả các lớp học trong truy cập dữ liệu lớp tôi có nguồn gốc từ một DALAncestor tổ tiên chung đó, trong số những thứ khác, xác định phương pháp GetData: public Danh sách trừu tượng GetData (Filter lọc)

An thực hiện phương pháp này cho Khách hàng sẽ trông như thế này (đã được đơn giản hóa):

public override List<Entities.Customer> GetData(Filter filter) { 
    var customers = from c in db.Customers 
        select new Entites.Customer { 
        ID = c.ID, 
        FullName = c.Name, 
        Country = c.Country 
        }; 

    return = filter.Apply(customers).ToList(); 
} 

"Áp dụng" là một phương pháp thu thập các điều kiện và áp dụng tất cả chúng bằng cách sử dụng LINQ động LINQ.

Phương pháp GetData được gọi là như thế này:

private void DemoCallGetDataMethod() { 
    var filter = new Filter(); 
    filter.AddCondition("Country", "Austria"); 

    var list = myCustomerDAL.GetData(filter); 
    // do something 
} 

SQL Server được một Statment chọn:

SELECT [t0].ID, [t0].Name, [t0].Country 
    FROM Customer [t0] 
WHERE [t0].Country = @p0 

(@ p0 là một tham số với giá trị của nó thiết lập để "Áo").

Mọi thứ hoạt động tốt, nếu tôi chỉ muốn lọc giá trị ở cấp "trên cùng" (chính). Tuy nhiên, vì tôi xây dựng bộ lọc dựa trên dữ liệu đầu vào của người dùng trên biểu mẫu bộ lọc, có những trường hợp người dùng muốn lọc theo giá trị ở cấp độ chi tiết (tức là các cột được lọc bởi chỉ được biết sau khi người dùng nhấp vào "Tìm kiếm").

Tôi không thể tìm thấy giải pháp cho việc này: "Nhận tất cả khách hàng từ Áo, người đã mua Pepsi".

Tôi đã thử nhiều thứ, không có thứ nào trong số đó có vẻ hoạt động. Ý tưởng cơ bản là:
1. Add support for CONTAINS để DynamicLibrary
2. Thay đổi mã của tôi để

public override List<Entities.Customer> GetData(Filter filter) { 
    var customers = from c in db.Customers 
        select new Entites.Customer { 
        ID = c.ID, 
        FullName = c.Name, 
        Country = c.Country, 
        Items = c.Order.SelectMany(o => o.Item).Select(i => i.ItemId).ToList() 
        }; 

    return = filter.Apply(customers).ToList(); 
} 

private void DemoCallGetDataMethod() { 
    var filter = new Filter(); 
    filter.AddCondition("Country","=", "Austria"); 
    filter.AddCondition("Items","Contains", "11"); // 11 = Id for Pepsi 

    var list = myCustomerDAL.GetData(filter); 

    // do something 
} 

các exepction ném là:

System.InvalidOperationException: Không có phương pháp chung 'Có' trên gõ 'System.Linq.Enumerable' tương thích với các đối số và đối số kiểu được cung cấp. Không có đối số kiểu nào được cung cấp nếu phương thức không chung chung.

Có ai biết tôi đang làm gì sai không? Hay tôi chỉ đi sai hướng và tôi nên thử một cách tiếp cận khác? Cái nào :)

EDITED: thay đổi ví dụ của tôi

+0

Xin lỗi Iam không chắc chắn những gì bạn đang sau, bài viết mà bạn đề cập cũng đã cung cấp một câu trả lời cho cùng một vấn đề bạn đang phải đối mặt để tránh ngoại lệ đó. Và bởi vì bạn muốn theo con đường đó, tôi thực sự không hiểu bạn là gì sau :)? – user182630

+0

filter.AddCondition ("Items", "Contains", "Pepsi"); - Điều này chỉ hoạt động đối với Chuỗi và Chuỗi, không phải Danh sách và chuỗi – Tsabo

+0

@ user182630 Tôi muốn có thể lọc theo giá trị từ các lựa chọn con nói chung, không chỉ cho một trường hợp cụ thể. Cách tiếp cận từ bài viết đó chỉ hoạt động nếu bạn mã cứng mà bạn lọc, đó không phải là điều tôi có thể làm. –

Trả lời

2

@ user182630 Tôi muốn để có thể lọc theo giá trị từ subselects trong nói chung, không chỉ đối với một trường hợp cụ thể. Cách tiếp cận từ bài viết đó chỉ hoạt động nếu bạn mã cứng mà bạn lọc, đó không phải là điều tôi có thể làm. - Marko Juvančič 9 mins ago

Có một chi qua bài viết này http://csharpindepth.com/articles/chapter5/closures.aspx

2

tôi sử dụng PredicateBuilder cho các truy vấn năng động trong các ứng dụng của tôi.

Predicate Builder

Trong trường hợp của bạn tôi tưởng tượng nó sẽ là một cái gì đó như:

string MyCountry = "Austria"; 
string MyProductId = 11 

var Predicate = PredicateBuilder.True<db.Customers>(); 
Predicate = Predicate.And(p=>p.Country ==MyCountry && p.Order.SelectMany(o=>o.Item).Where(i=>i.id == 11).Count() >0); 

var list = Customers.Where(Predicate).Select(s=>s).ToList(); 
+0

Cách tiếp cận này không thành công trên "cột được lọc bởi chỉ được biết sau khi người dùng nhấp vào Tìm kiếm" yêu cầu. –

+0

Vâng, nếu tất cả các cột được biết trước thì đây không phải là một vấn đề. – Tsabo

+0

Họ không. Phương pháp "Áp dụng" bộ lọc không biết gì về các cột. –

Các vấn đề liên quan