2011-08-29 89 views
10

Tôi đang phát triển một ứng dụng ASP.NET MVC 3 sử dụng C# và Razor.Làm thế nào để thực hiện chức năng tìm kiếm trong C#/ASP.NET MVC

Tôi có một hình thức tìm kiếm mà trông như thế này: searchform

Các hình thức tìm kiếm hoạt động theo cách sau:

  1. Người dùng chọn mà tài sản mà họ muốn tìm kiếm trên.
  2. Người dùng chọn cách họ muốn khớp với chuỗi tìm kiếm (ví dụ: chứa, bắt đầu bằng, kết thúc bằng, bằng, v.v.).
  3. Người dùng nhập cụm từ tìm kiếm và nhấp vào Tìm kiếm.

Các lựa chọn trong menu thả xuống đầu tiên có liên quan trực tiếp đến thuộc tính trong lớp mô hình Khung thực thể ADO.NET của tôi (và do đó trực tiếp đến cột bảng).

Người dùng cần có khả năng chọn rõ thuộc tính nào và phương thức đối sánh nào khi tìm kiếm, ví dụ: người dùng sẽ tìm kiếm tất cả các kết quả phù hợp với số tiến trình bằng '132'.

Cách tiếp cận đầu tiên của tôi là sử dụng LINQ động để xây dựng mệnh đề Where từ tiêu chí tìm kiếm (see my original question). Tuy nhiên tôi bắt đầu nghĩ rằng đây không phải là cách tốt nhất để làm điều đó.

Tôi cũng hy vọng một giải pháp không yêu cầu tôi phải mã hóa cứng kết quả cho mỗi kết hợp tiêu chí của thuộc tính + đối sánh.

Bất kỳ đề xuất nào về cách tôi nên triển khai tìm kiếm này? Nó không phải sử dụng mẫu tìm kiếm hiện tại của tôi, hoàn toàn mở ra cho bất kỳ ý tưởng nào khác phù hợp với yêu cầu.

+7

bạn biết đấy, đây là thời trang cũ soooo! Trong ứng dụng của chúng tôi, chúng tôi sẽ tìm kiếm nhanh chóng đơn giản như thanh địa chỉ của Google Chrome hoặc IE 9, nơi bạn có thể nhập url hoặc tìm kiếm theo văn bản. Không cần phải chỉ định tên cột hoặc điều kiện, chỉ cần thực hiện tìm kiếm văn bản đầy đủ trên các cột có ý nghĩa và kết hợp kết quả với các kết hợp có thể khác, trải nghiệm người dùng dễ dàng và mượt mà hơn, người dùng của chúng tôi yêu thích điều này, sau giai đoạn đầu tiên của "cảm thấy mất": D –

+3

Tôi không chắc liệu loại tìm kiếm đó có cung cấp tính đặc hiệu cần thiết cho người dùng của chúng tôi hay không. Họ cần để có thể xác định rõ ràng cho dù họ muốn có chứa, bằng, vv, và tôi muốn tránh buộc họ phải tìm hiểu một số cú pháp chuỗi để thực hiện điều này. Hãy đặt đề xuất của bạn như một câu trả lời. – link664

+0

Nếu bạn mô hình hóa Thuộc tính, Toán tử và Thuật ngữ là 3 thực thể riêng biệt, tôi không hiểu tại sao tùy chọn 'LINQ động' sẽ buộc bạn phải mã hóa bất cứ thứ gì? Bạn sẽ xây dựng truy vấn LINQ mong đợi - như một chuỗi - từ thông tin được thu thập từ 3 thực thể. Ví dụ: bạn có thể tạo thuộc tính LinkOperation cho thực thể Toán tử sẽ giúp bạn tạo chuỗi này. –

Trả lời

3

Bạn có thể tạo cây biểu thức cho vị ngữ sử dụng mã. Ví dụ:

public static IQueryable<T> DynamicWhere<T>(this IQueryable<T> src, string propertyName, string value) 
{ 
    var pe = Expression.Parameter(typeof(T), "t"); 
    var left = Expression.Property(pe, typeof(T).GetProperty(propertyName)); 
    var right = Expression.Constant(value); 
    // Illustrated a equality condition but you can put a switch based on some parameter 
    // to have different operators 
    var condition = Expression.Equal(left, right); 

    var predicate = Expression.Lambda<Func<T, bool>>(condition, pe); 
    return src.Where(predicate); 
} 

Sử dụng nó làm Orders.DynamicWhere(searchBy, searchValue). Bạn có thể thêm một tham số khác để chấp nhận toán tử như Equals, Greater Than vv để hoàn thành hàm.

Xem những liên kết này để biết thêm:

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

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

Ngoài ra kiểm tra list of methods on the Expression class để có được một ý tưởng.

+0

Điều này có vẻ như một cách tiếp cận tuyệt vời. Cảm ơn. Thật không may, trong trường hợp của tôi, tôi cần phải so sánh một thuộc tính trong một bảng liên quan với 'T'. (Bảng kia có FK với bảng 'T' của tôi nhưng tôi chỉ quan tâm đến một hàng nếu có vô tình nữa.) Sau khi dành nhiều thời gian cho việc này, tôi không thể thấy cách tôi có thể sửa đổi điều này để hỗ trợ một thuộc tính trong một bảng liên quan. –

12

Bạn đã xem xét sử dụng Lucene.NET cho dự án này chưa? với bản chất của các tìm kiếm của bạn, việc tạo các bộ lọc trên các cột khác nhau cũng giống như yêu cầu của bạn, vì nó cho phép bạn kết hợp các bộ lọc trên các cột khác nhau giống như các yêu cầu của bạn

+0

Lucene có phải là thư viện tìm kiếm/lập chỉ mục tài liệu không? Tìm kiếm của tôi không phải là tìm kiếm trên các trang/nội dung trong các trang, chúng là các tìm kiếm trên mô hình Khung thực thể. – link664

+0

Lucene tốt cho việc lập chỉ mục toàn văn. Nhưng SQL Server cũng có một dịch vụ lập chỉ mục văn bản đầy đủ. Tôi cũng nên chỉ ra rằng tìm kiếm toàn văn chỉ là một loại tìm kiếm. –

+0

Chính xác. Và tôi không chắc cách lập chỉ mục văn bản đầy đủ sẽ giúp tôi trong trường hợp này khi tôi không chỉ làm một tấm chăn "tìm thấy tôi mọi thứ trong cơ sở dữ liệu của tôi có chứa giá trị này" loại tìm kiếm. – link664

0

Bạn có thể sử dụng Dynamic Linq và bạn có thể tạo ra clausole Where with a utility lớp học như thế này:

public class Criteria 
{ 
    StringBuilder sb = new StringBuilder(); 
    bool first = true; 

    public void And(string property, string dbOperator, string value) { 
     if (first) 
     { 
      sb.Append(" ").Append(property).Append(" "); 
      sb.Append(" ").Append(dbOperator).Append(" "); 
      sb.Append(" ").Append(value).Append(" "); 
      first = false; 
     } 
     else 
     { 
      sb.Append(" && ").Append(property).Append(" "); 
      sb.Append(" ").Append(dbOperator).Append(" "); 
      sb.Append(" ").Append(value).Append(" "); 
     } 
    } 

    public void Or(string property, string dbOperator, string value) 
    { 
     if (first) 
     { 
      sb.Append(" ").Append(property).Append(" "); 
      sb.Append(" ").Append(dbOperator).Append(" "); 
      sb.Append(" ").Append(value).Append(" "); 
      first = false; 
     } 
     else 
     { 
      sb.Append(" || ").Append(property).Append(" "); 
      sb.Append(" ").Append(dbOperator).Append(" "); 
      sb.Append(" ").Append(value).Append(" "); 
     } 
    } 

    public string ToString() 
    { 
     return sb.ToString(); 
    } 

} 

Vì vậy, bạn có thể tạo Tiêu chí có nhiều thuộc tính bằng cách sử dụng Hoặc hoặc phương pháp và đặt nó vào Nhà điều hành địa điểm của LINQ động.

0

Chúng tôi đã bắt đầu giải quyết các truy vấn tương tự đối với mô hình Khung thực thể của chúng tôi bằng cách sử dụng truy vấn LINQ động.Tuy nhiên, nỗ lực của chúng tôi để khái quát hóa việc tạo truy vấn dẫn đến hiệu suất kém do EF bị nhầm lẫn bởi các biểu thức phức tạp, do đó, trong SQL kết thúc khủng khiếp được tạo ra.

Chúng tôi đã sử dụng đến Entity SQL.

0

Không chắc chắn nếu bạn đang sử dụng MS SQL. Dường như SQL có thể thực hiện hầu hết công việc cho bạn và bạn có thể tạo các truy vấn động. Rõ ràng câu lệnh select/from cần làm việc, nhưng bạn có thể lấy ý tưởng từ mệnh đề where.

DECLARE @SEARCHTYPE VARCHAR(20) 
DECLARE @SEARCHTERM VARCHAR(100) 

SELECT 
    [FIELDS] 
FROM 
    [TABLE] 
WHERE 
    (@SEARCHTYPE = 'BEGINSWITH' AND [FIELD] LIKE @SEARCHTERM + '%') OR 
    (@SEARCHTYPE = 'ENDSWITH' AND [FIELD] LIKE '%' + @SEARCHTERM) OR 
    (@SEARCHTYPE = 'EQUALS' AND [FIELD] = @SEARCHTERM) 
0

Bạn có thể có nguồn dữ liệu kết hợp đầu tiên thiết lập để myEntityObject.GetType() GetProperties(), thứ hai đến một danh sách các thể hiển thị Funcs<string, string, bool>, như thế này:.

public class ComboPredicate 
{ 
    public Func<string, string, bool> Func {get; set;} 
    public string Name {get; set; } 
} 

Sau đó, khi bạn tải các hình thức:

comboProperty.Datasource = myEntityObject.GetType().GetProperties() 
comboOperation.Datasource = new List<Predicate> 
    { 
     { 
      Name = "Contains", 
      Predicate = (s1, s2) => s1 != null && s1.Contains(s2), 
     }, 
     { 
      Name = "Equals", 
      Predicate = (s1, s2) => string.Compare(s1, s2) == 0, 
     }, 
     //... 
    } 

Và sau đó, khi bạn muốn chọn các đơn vị của bạn:

var propertyInfo = (PropertyInfo)comboProperty.SelectedValue; 
var predicate = ((ComboPredicate)comboOperation.SelectedValue).Predicate; 
var filteredObjects = objects.Where(o => predicate(propertyInfo.GetValue(o, null).ToString(), textBoxValue.Text)); 
0

tạo phương pháp và gọi nó vào nút nhấp chuột giới thiệu dưới đây

public List gettaskssdata (int c, int userid, chuỗi một chuỗi StartDate, chuỗi EndDate, chuỗi ProjectID, chuỗi statusid) {

 List<tbltask> tbtask = new List<tbltask>(); 


     var selectproject = entity.tbluserprojects.Where(x => x.user_id == userid).Select(x => x.Projectid); 

     if (statusid != "" && ProjectID != "" && a != "" && StartDate != "" && EndDate != "") 
     { 
      int pid = Convert.ToInt32(ProjectID); 
      int sid = Convert.ToInt32(statusid); 
      DateTime sdate = Convert.ToDateTime(StartDate).Date; 
      DateTime edate = Convert.ToDateTime(EndDate).Date; 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid) && (x.tblstatu.StatusId == sid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     else if (statusid == "" && ProjectID != "" && a != "" && StartDate != "" && EndDate != "") 
     { 
      int pid = Convert.ToInt32(ProjectID); 
      DateTime sdate = Convert.ToDateTime(StartDate).Date; 
      DateTime edate = Convert.ToDateTime(EndDate).Date; 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     else if (ProjectID == "" && statusid != "" && a != "" && StartDate != "" && EndDate != "") 
     { 
      int sid = Convert.ToInt32(statusid); 
      DateTime sdate = Convert.ToDateTime(StartDate).Date; 
      DateTime edate = Convert.ToDateTime(EndDate).Date; 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblstatu.StatusId == sid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     else if(ProjectID!="" && StartDate == "" && EndDate == "" && statusid == "" && a == "") 
     { 
      int pid = Convert.ToInt32(ProjectID); 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid)).OrderByDescending(x => x.ProjectId).ToList(); 

     } 
     else if(statusid!="" && ProjectID=="" && StartDate == "" && EndDate == "" && a == "") 
     { 
      int sid = Convert.ToInt32(statusid); 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblstatu.StatusId == sid)).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     else if (a == "" && StartDate != "" && EndDate != "" && ProjectID != "") 
     { 
      int pid = Convert.ToInt32(ProjectID); 
      DateTime sdate = Convert.ToDateTime(StartDate).Date; 
      DateTime edate = Convert.ToDateTime(EndDate).Date; 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.ProjectId == pid) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); 

     } 
     else if (StartDate == "" && EndDate == "" && statusid != "" && ProjectID != "" && a != "") 
     { 
      int pid = Convert.ToInt32(ProjectID); 
      int sid = Convert.ToInt32(statusid); 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid) && (x.tblstatu.StatusId == sid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a))).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     else if (a == "" && StartDate == "" && EndDate == "" && ProjectID != "" && statusid != "") 
     { 
      int pid = Convert.ToInt32(ProjectID); 
      int sid = Convert.ToInt32(statusid); 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Include(x => x.tblstatu).Where(x => selectproject.Contains(x.ProjectId) && x.tblproject.company_id == c && x.tblproject.ProjectId == pid && x.tblstatu.StatusId == sid).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     else if (a != "" && StartDate == "" && EndDate == "" && ProjectID == "" && statusid == "") 
     { 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a))).OrderByDescending(x => x.ProjectId).ToList(); 

     } 
     else if (a != "" && ProjectID != "" && StartDate == "" && EndDate == "" && statusid == "") 
     { 
      int pid = Convert.ToInt32(ProjectID); 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.tblproject.ProjectId == pid) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a))).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     else if (a != "" && StartDate != "" && EndDate != "" && ProjectID == "" && statusid == "") 
     { 
      DateTime sdate = Convert.ToDateTime(StartDate).Date; 
      DateTime edate = Convert.ToDateTime(EndDate).Date; 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && (x.tblproject.company_id == c) && (x.TaskName.Contains(a) || x.tbUser.User_name.Contains(a)) && (x.StartDate >= sdate && x.EndDate <= edate)).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     else 
     { 
      tbtask = entity.tbltasks.Include(x => x.tblproject).Include(x => x.tbUser).Where(x => selectproject.Contains(x.ProjectId) && x.tblproject.company_id == c).OrderByDescending(x => x.ProjectId).ToList(); 
     } 
     return tbtask; 

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