2011-03-11 26 views
0

我有一個WebForm與4個組合框,它允許用戶定義不同的搜索條件。如果用戶在組合框中沒有選擇任何東西,這意味着用戶想要選擇這個標準中的所有數據(換句話說,省略過濾器)。如何將多標準搜索應用於LINQ?

這個想法很簡單,但是當我在Linq中實現它時,它痛苦。我不知道如何可選地將條件添加到查詢中。這裏是我的「概念」查詢,當然這是不起作用的:

var context = new Entities(); 
     var complaints = from c in context.Complaints 
         join s in context.Statuses on c.Status equals s.Id 
         join service in context.SERVICES on c.ServiceId equals service.Id 
         join u in context.Users on c.CreatedBy equals u.UserId 
         from technician in context.Users.Where(technician => technician.UserId == c.AssignedTo).DefaultIfEmpty() 
         where c.ResellerId == CurrentUser.ResellerID 
         && c.CreatedBy == (decimal)ASPxComboBoxSupporter.Value //if Supporter is selected and so on 
         && c.AssignedTo == (decimal)ASPxComboBoxTechnician.Value 
         && c.ServiceId == (decimal)ddlService.Value 
         && c.Status == (decimal)ddlStatus.Value 
         select new 
         { 
          c.Id, 
          c.Status, 
          s.Name, 
          c.ServiceId, 
          Service = service.Name, 
          c.Title, 
          c.Customer, 
          c.Description, 
          c.CreatedDate, 
          c.CreatedBy, 
          Author = u.Username, 
          c.AssignedBy, 
          c.AssignedTo, 
          Technician = technician.Username, 
          c.AssignedDate 
         }; 

我該怎麼做?

回答

1

首先,您必須解析用戶輸入的文本,看它是否真的是數字,如果是,則將其轉換爲decimal類型。有一個方便的方法decimal.TryParse爲:

decimal supporter; 
    bool supportedSpecified = decimal.TryParse(ASPxComboBoxSupporter.Value, out supporter); 

然後你就可以在查詢中使用這樣的信息:

where c.ResellerId == CurrentUser.ResellerID 
    && (!supporterSpecified || c.CreatedBy == supporter) 
    ... 

重複的其他標準。

+0

工程很好,但有一個小缺陷:decimal.TryParse不能把第一個參數作爲對象,而是字符串。我改爲ASPxComboBoxSupporter.Value作爲字符串,它的工作:) – Vimvq1987 2011-03-11 06:58:44

3

您可以嘗試利用IQueryable對象的工作方式,而不是使用更多SQL樣式的Linq語法創建它(對不起,我不知道它的正確名稱)。基本上你可以做的是在需要的地方添加where子句,否則省略它們。沿着這些線路的東西應該工作:

var context = new Entities(); 
var complaints = from c in context.Complaints 
       join s in context.Statuses on c.Status equals s.Id 
       join service in context.SERVICES on c.ServiceId equals service.Id 
       join u in context.Users on c.CreatedBy equals u.UserId 
       from technician in context.Users.Where(technician => technician.UserId == c.AssignedTo).DefaultIfEmpty() 
       select new 
       { 
        c.Id, 
        c.Status, 
        s.Name, 
        c.ServiceId, 
        Service = service.Name, 
        c.Title, 
        c.Customer, 
        c.Description, 
        c.CreatedDate, 
        c.CreatedBy, 
        Author = u.Username, 
        c.AssignedBy, 
        c.AssignedTo, 
        Technician = technician.Username, 
        c.AssignedDate 
       }; 

所以請記住,你還沒有真正質疑任何事情,因爲LINQ的使用延遲執行。現在,你可以通過添加where子句

if (ASPxComboBoxSupporter.Value != null) 
{ 
    complaints = complaints.Where(c => c.CreatedBy == (decimal)ASPxComboBoxSupporter.Value); 
} 
if (ASPxComboBoxTechnician.Value != null) 
{ 
    complaints = complaints.Where(c => c.AssignedTo == (decimal)ASPxComboBoxTechnician.Value); 
} 

if (ddlService.Value != null) 
{ 
    complaints = complaints.Where(c => c.ServiceId == (decimal)ddlService.Value); 
} 

if (ddlStatus.Value != null) 
{ 
    complaints = complaints.Where(c => c.Status == (decimal)ddlStatus.Value); 
} 

我沒有測試過這一點,所以讓我知道如果有什麼不工作還不錯。

+0

我實際上實現了這個作爲我們自己的多標準搜索的解決方案,它的工作原理非常漂亮。它具有額外的好處,只有在需要時纔會變得複雜。 – 2012-11-30 09:53:20

1

請看一下C#中簡明書中描述的the PredicateBuilder class。它允許您動態構建一個謂詞,以便與LINQ to SQL和Entity Framework一起使用。