2009-02-28 32 views
11

Tôi có một bảng khóa học mà tôi cần tìm kiếm dựa trên các từ khóa được nhập vào hộp tìm kiếm. Đây là một truy vấn mẫu:LINQ nhiều nơi khoản

SELECT * FROM Courses WHERE 
Title LIKE '%word%' OR Title LIKE '%excel%' OR 
Contents LIKE '%word%' OR Contents LIKE '%excel%' 

Làm thế nào tôi có thể chuyển đổi này trong LINQ nơi LINQ sẽ tự động tạo ĐÂU báo cáo dựa trên mỗi từ khóa.

Tôi đã cố gắng sử dụng PredicateBuilder nó hoạt động tốt miễn là trường này là VARCHAR. Đối với các trường "TEXT", các dấu trích dẫn không được tạo ra, do đó làm cho trình biên dịch đưa ra một thông báo lỗi. Đây là SQL được tạo bởi PredicateBuilder

SELECT [t0].[CoursesID], [t0].[Title], [t0].[Contents], [t0].[Active], 
FROM [dbo].[Courses] AS [t0] 
WHERE ([t0].[Title] LIKE '%word%') OR ([t0].[Contents] LIKE %word%) OR 
([t0].Title] LIKE '%excel%') OR ([t0].[Contents] LIKE %excel%) 

Lưu ý rằng không có Trích dẫn đơn cho trường "Nội dung" là trường Văn bản trong cơ sở dữ liệu.

Có cách nào dễ dàng để xây dựng câu lệnh WHERE và đính kèm nó với truy vấn không? Có ai biết làm thế nào tôi có thể làm điều này mà không có PredicateBuilder?

Xin cảm ơn trước.

Trả lời

13

Vì bạn đang làm việc w/LINQ Tôi cho rằng bạn đang làm việc với bối cảnh dữ liệu LINQ-to-SQL phải không? Tôi không có một DataContext dự phòng nằm xung quanh để kiểm tra điều này, nhưng điều này sẽ cung cấp cho bạn một số ý tưởng. Tuy nhiên, hầu hết chúng là những thứ khá cơ bản (chuỗi OR operator và Chứa lời gọi phương thức) nên nó không gây ra vấn đề khi truy vấn dịch sang SQL.

Trước tiên tôi tạo ra một chức năng tùy chỉnh mà sẽ xây dựng ngữ của tôi:

Func<string, Func<DataItem, bool>> buildKeywordPredicate = 
    keyword => 
     x => x.Title.Contains(keyword) 
      || x.Contents.Contains(keyword); 

Đây là một chức năng mà phải mất một từ khóa chuỗi đơn và sau đó trở về một chức năng mà phải mất một DataItem và kiểm tra nó chống lại các từ khóa.

Về cơ bản, nếu bạn chuyển vào "Ngăn xếp", bạn sẽ nhận được vị từ: x => x.Title.Contains("Stack") || x.Contents.Contains("Stack").

Tiếp theo, vì có nhiều từ khóa càng tốt và bạn cần phải xích nó với một hoạt động OR, tôi tạo ra một chức năng helper để chuỗi 2 vị cùng với một HOẶC

Func<Func<DataItem,bool>, Func<DataItem, bool>, Func<DataItem, bool>> buildOrPredicate = 
    (pred1, pred2) => 
     x => pred1(x) || pred2(x); 

chức năng này có 2 vị từ và sau đó tham gia chúng với một hoạt động OR.

Có những 2 chức năng, sau đó tôi có thể xây dựng của tôi, nơi vị như thế này:

foreach (var word in keywords) {    
    filter = filter == null 
     ? buildKeywordPredicate(word) 
     : buildOrPredicate(filter, buildKeywordPredicate(word)); 
} 

Dòng đầu tiên bên trong vòng lặp cơ bản kiểm tra nếu bộ lọc là null. Nếu có, thì chúng tôi muốn có một bộ lọc từ khóa đơn giản được xây dựng cho chúng tôi.

Khác nếu bộ lọc không rỗng, chúng tôi cần chuỗi các bộ lọc hiện có bằng thao tác OR, vì vậy chúng tôi vượt qua bộ lọc hiện tại và bộ lọc từ khóa mới để xây dựngOrPredicate để thực hiện điều đó.

Và rồi bây giờ chúng tôi có thể tạo ra các phần WHERE của truy vấn:

var result = data.Where(filter); 

Đi qua trong vị ngữ phức tạp chúng ta vừa xây dựng.

Tôi không biết điều này sẽ khác với việc sử dụng PredicateBuilder hay không nhưng vì chúng tôi trì hoãn việc dịch truy vấn sang công cụ LINQ-to-SQL, nên không có bất kỳ vấn đề gì.

Nhưng như tôi đã nói, tôi không thử nghiệm nó dựa trên bối cảnh dữ liệu thực, vì vậy nếu có bất kỳ vấn đề nào bạn có thể viết trong phần bình luận.

Dưới đây là các ứng dụng giao diện điều khiển mà tôi xây dựng để kiểm tra: http://pastebin.com/feb8cc1e

Hope this helps!


EDIT: Đối với một phiên bản chung chung hơn và tái sử dụng trong đó bao gồm việc sử dụng đúng cách các cây Expression trong LINQ, hãy kiểm tra bài viết trên blog Thomas Petricek của: http://tomasp.net/articles/dynamic-linq-queries.aspx

+1

này unfortunatelly sẽ chỉ làm việc cho các chức năng. Để thực hiện công việc này với cây biểu thức, bạn cần sử dụng một mẹo như sau: http://tomasp.net/articles/dynamic-linq-queries.aspx –

+0

Đó là một số thành tích bạn đã làm ở đó! và nhiều hơn nữa awesomeness ... Dù sao, tôi là một thuê bao của blog của bạn bây giờ :-) – chakrit

+0

Cảm ơn, điều này đã làm việc. http://tomasp.net/articles/dynamic-linq-queries.aspx - Tomas Petricek – Amir

0

Vì trình tạo ngữ nghĩa không biết loại DB của thuộc tính mà phương thức Chứa được gọi, tôi đoán đây có thể là một vấn đề bên trong LINQ thành sql. Bạn đã thử với một truy vấn bình thường (không phải với trình tạo vị ngữ) và cột TEXT có chứa?

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