2012-11-05 32 views
4

我試圖將一些直接構建SQL查詢的舊代碼轉換爲實體框架,並且遇到了很多似乎都存在的問題(從大量問題主題):如何在linq中表達動態條件。Linq-to-Entities查詢中的動態條件

我怎麼能表達對LINQ查詢下面的代碼:

switch (status) { 
     case "0": 
      sqlwhere = " WHERE status < 0 "; 
      break; 
     case "-1": 
      sqlwhere = " WHERE status = -1 "; 
      break; 
     case "-100": 
      sqlwhere = " WHERE status = -100 "; 
      break; 
     case "1": 
     default: 
      sqlwhere = " WHERE status >= 0 "; 
      break; 
    } 

    if (strsearch != "") 
     sqlwhere += " AND desc LIKE '%" + strsearch + "%' "; 

    string sqlc = "SELECT top 10 * FROM c " + sqlwhere + " order by date desc"; 

我讀過有關PredicateBuilder和其他職位的動態擴展的LINQ,但我認爲這是一個簡單的情況下可能是沒有解外部庫。

使用.net 4.5,EF 5.0,C#,這可以以「動態」的方式完成,無需爲每個單獨的情況構建完整的linq語句?

+1

'查詢= query.Where(X => x.status < 0)' –

回答

2

如果你不想用外在的東西,然後只需用流利的API:

var query = db.YourTableName 
       .Where(x => x.desc.Contains(strsearch)); 

switch (status) { 
    case "0": 
     query = query.Where(x => x.status < 0); 
     break; 
    case "-1": 
     query = query.Where(x => x.status == -1); 
     break; 
    case "-100": 
     query = query.Where(x => x.status == -100); 
     break; 
    case "1": 
    default: 
     query = query.Where(x => x.status >= 0); 
     break; 
} 

var result = query.OrderByDescending(x => x.date) 
        .Take(10); 

BTW您可以創建按狀態過濾的擴展方法。和您的查詢將是這樣的:

var query = db.YourTableName 
       .FilterByStatus(status) 
       .Where(x => x.desc.Contains(strsearch)) 
       .OrderByDescending(x => x.date) 
       .Take(10); 

擴展方法:

public static IQueryable<YourType> FilterByStatus(this IQueryable<YourType> query, 
                string status) 
{ 

    switch (status) { 
     case "0": 
      return query.Where(x => x.status < 0);    
     case "-1": 
      return query.Where(x => x.status == -1); 
     case "-100": 
      return query.Where(x => x.status == -100); 
     case "1": 
     default: 
      return query.Where(x => x.status >= 0); 
    } 
} 
+0

與上述流暢的api語法將全部轉換爲一個sql查詢,導致只有一個數據庫往返?所有過濾,排序等都將在數據庫中完成,這一點很重要,因爲不要檢索數千條記錄,然後過濾客戶端。 – Tom

+0

@Tom,是的,它會是一個數據庫查詢,Linq會推遲執行,直到你調用類似'foreach','ToList'或'Count'的東西。 –

+0

謝謝,那就是我一直在尋找的東西。所以只要我只需要動態添加AND條件(或設置排序),我就可以使用它來代替PredicateBuilder等擴展。 – Tom

2

在你的情況下使用PredicateBuilder像如下

還檢查我的博客文章:Dynamic query with Linq

var outer = PredicateBuilder.True<Entity>(); 

switch (status) { 
     case "0": 
      outer = outer.And (p => p.status<0); 
      break; 
     case "-1": 
      outer = outer.And (p => p.status==-1); 
      break; 
     case "-100": 
      outer = outer.And (p => p.status==-100); 
      break; 
     case "1": 
     default: 
      outer = outer.And (p => p.status>=0); 
      break; 
    } 

if (strsearch != "") 
     outer = outer.And (p => p.desc.Contains(strsearch)); 

dataContext.Entity.Where (outer); 
+0

感謝您的答案和鏈接 - 雖然這是更強大的,我一直在尋找一個沒有「extenions」的解決方案。 – Tom

0

可以使用LinkExtensionLinqKit

using (var context = new workEntities()) 
{ 

    Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>(); 
    dictionary["Title"] = new List<string> { 
        "Network Engineer", 
        "Security Specialist", 
        "=Web Developer" 
       }; 
    dictionary["Salary"] = new List<string> { ">=2000" }; 
    dictionary["VacationHours"] = new List<string> { ">21" }; 
    dictionary["SickLeaveHours"] = new List<string> { "<5" };     
    dictionary["HireDate"] = new List<string> { 
        ">=01/01/2000", 
        "28/02/2014" 
       }; 
    dictionary["ModifiedDate"] = new List<string> { DateTime.Now.ToString() }; 

    var data = context.Employee.CollectionToQuery(dictionary).ToList(); 
}