2013-04-10 37 views
5

tôi cần phải viết một số phương pháp tìm kiếm chung chung như thế này:C# Generic LINQ Query

public List<T> Search<T>(SearchParamsBase searchParams) 
{ 
    using (var context = new TestEntities()) 
    { 
     var dataType = TypeMap.Get(typeof (T)); 
     var dataSet = context.Set(dataType); 

     var searchQuery = CreateQuery((IEnumerable<object>) dataSet), searchParams) 

     return searchQuery.ToList() 
    } 
} 

và tôi có một hàm CreateQuery() rằng nên lọc IEnumerable đối tượng. Chức năng này sẽ khác đối với tất cả các lớp. Ví dụ:

CreateQuery(IEnumerable<object> collection, SearchParamsBase searchParams) 
{ 
    var search = (SomeSearchImplementation)searchParams; 
    // filter 
    collection = collection.Where(x => x.Name == search.Name); 
    // select page 
    collection = collection.Skip(search.Page * search.CountPerPage); 
    collection = collection.Take(search.CountPerPage); 
    // order by and so on 
    // ... 
    return collection; 
} 

Làm cách nào để triển khai ý tưởng này một cách chính xác?

Trả lời

7

Những gì bạn về cơ bản muốn làm ở đây là xây dựng một truy vấn LINQ động. Để làm điều này, bạn cần phải sửa đổi/xây dựng cây biểu thức trong thời gian chạy. Nếu bạn không quen thuộc với cây biểu hiện và loại Expression<T> Tôi khuyên bạn nên bài viết này và các trang tham chiếu trong "Xem thêm" phần:

http://msdn.microsoft.com/en-us/library/bb397951.aspx

Bây giờ bạn bây giờ khái niệm cơ bản, chúng ta hãy thực hiện phân loại năng động. Phương thức bên dưới là phần mở rộng cho IQueryable<T> có nghĩa là nó không chỉ áp dụng cho danh sách mà còn cho mọi nguồn dữ liệu LINQ, vì vậy bạn cũng có thể sử dụng nó trực tiếp đối với cơ sở dữ liệu (hiệu quả hơn khi phân trang và phân loại hơn trong hoạt động bộ nhớ) . Phương pháp này có tên thuộc tính bạn muốn đặt hàng bằng và sự chỉ đạo sắp xếp (tăng dần/giảm dần):

public static IQueryable<T> OrderByDynamic<T>(this IQueryable<T> query, string sortColumn, bool descending) 
{ 
    // Dynamically creates a call like this: query.OrderBy(p => p.SortColumn) 
    var parameter = Expression.Parameter(typeof(T), "p"); 

    string command = "OrderBy"; 

    if (descending) 
    { 
     command = "OrderByDescending"; 
    } 

    Expression resultExpression = null;  

    var property = typeof(T).GetProperty(sortColumn); 
    // this is the part p.SortColumn 
    var propertyAccess = Expression.MakeMemberAccess(parameter, property); 

    // this is the part p => p.SortColumn 
    var orderByExpression = Expression.Lambda(propertyAccess, parameter); 

    // finally, call the "OrderBy"/"OrderByDescending" method with the order by lamba expression 
    resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { typeof(T), property.PropertyType }, 
     query.Expression, Expression.Quote(orderByExpression)); 

    return query.Provider.CreateQuery<T>(resultExpression); 
} 

Bây giờ bạn có thể viết mã này để đặt hàng các bộ dữ liệu của thuộc tính Name trong ascending theo thứ tự:

dataSet.OrderByDynamic("Name", false) 

Tạo phương pháp tiện ích mở rộng để lọc động sau cùng một mẫu. Nếu bạn hiểu mã ở trên, nó sẽ không có vấn đề gì với bạn.

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