2014-04-28 127 views
0

我目前正在將舊系統遷移到.Net,並且我遇到了這個問題。 我想返回結果,但我仍然需要在函數後對其進行優化,但使用此代碼,我沒有選擇,只能調用數據庫的結果並過濾內存中的結果,而不是性能差。LINQ到實體的動態查詢

public IQueryable<User> GetUser(string[] accessCodes) 
{ 
    string condition = ""; 
    if (accessCodes == null) 
    { 
     condition = " AccessCode IS NOT NULL " 
    } 
    else 
    { 
     for (int i = 0; i <= accessCodes.Length - 1; i++) 
     { 
      condition += " AccessCode LIKE '%" + accessCodes[i].ToString() + "%' "; 
      if (i + 1 <= code.Length - 1) 
      { 
       condition += " OR "; 
      } 
     } 
    } 

    return context.ExecuteQuery<User>("SELECT * FROM User WHERE " + condition, null).ToList(); 
} 

我試過這種方法,但我又卡:

public IQueryable<User> GetUser(string[] accessCodes) 
{ 
    IQueryable<User> basequery = from u in context.User 
           select u; 

    if (accessCodes == null) 
    { 
     basequery = basequery.Where(n => n.AccessCode != null); 
    } 
    else 
    { 
     for (int i = 0; i <= accessCodes.Length - 1; i++) 
     { 
      // what am I supposed to do here? 
     } 
    } 

    return basequery; 
} 

我希望有不需要第三方庫的解決方案。

+0

你能否簡單地解釋一下你試圖達到的目標?你想根據什麼標準過濾用戶? –

回答

1

您可以Any嘗試:

else 
{ 
    output = output.Where(u => accessCodes.Any(a => u.AccessCode.Contains(a))); 
} 

,或者您可以使用PredicateBuilder

if (accessCodes == null) 
{ 
    output = output.Where(u => u.AccessCode == null); 
} 
else 
{ 
    var predicate = PredicateBuilder.False<User>(); 

    for (int i = 0; i <= accessCodes.Length - 1; i++) 
    { 
     predicate = predicate.Or(u => u.AccessCode.Contains(accessCodes[i])) 
    } 

    output = output.Where(predicate); 
} 

我也改變了你的if部分:Where方法不修改源,它返回新的查詢定義,所以你必須把它分配回output才能使它工作。

+0

嗨,Marcin,當我使用「.Any」時,它引發一個異常「DbExpressionBinding需要一個帶有集合ResultType的輸入表達式。」 我試過直接使用謂詞構建器,它也會引發錯誤「不支持LINQ表達式節點類型」Invoke「」。我讀過PredicateBuilder指令,爲了在實體框架中使用PredicateBuilder,我需要使用「LINQKit.dll」。有沒有任何工作,而不使用LINQKit.dll? – arvstracthoughts

+0

嗨,沒關係,.Any()就足夠了,似乎我一直在使用char []而不是string []來引發異常。 – arvstracthoughts

1

這應該爲你工作:

IQueryable<User> basequery = from u in context.User 
          select u; 
if (accessCodes == null) 
{ 
    basequery = basequery.Where(u => u.AccessCode != null); 
} 
else 
{ 
    basequery = basequery.Where(u => accessCodes.Contains(u=>u.AccessCode)); 
} 

也確保您返回basequery,因爲在你的方法output沒有定義,並且不使用。

+0

這將工作,如果只有一個訪問代碼,但正如我上面發佈,有時需要多個訪問代碼,這就是爲什麼它是在一個循環內。 – arvstracthoughts

+0

accessCodes.Contains(u => u.AccessCode)它會產生你所需要的。 'Contains'正確地遍歷代碼和linq句柄。使用你的'ToTraceString()'方法檢查輸出查詢。 – Andrew

+0

.Contains是不夠的,假設accessCode只由字符串「m」組成,它必須檢索「m」,「mx」,「m3」,「mp」而不是「m」。 – arvstracthoughts