2014-09-23 77 views
2

我有一個數據庫,我沒有創建,我不能修改。我需要運行一個linq查詢,但我需要在where子句中傳入一個變量。LINQ中可變條件where子句

列在表:AdvMonAM(所有位),AdvMonAMAdvTueAMAdvTuePMAdvWedAM

var column = "Adv" + dayOfWeek + time; 
var employeesOnCall = from r in db.AdvOnCalls 
         where (variable column needed here) == true 
         select r.ChartEmployee; 

如果我硬編碼r.AdvTueAM它完美,而是r.column == truecolumn == true沒有。我覺得這應該是一件容易的事,但我很難過。

我試圖找到那些呼叫在一天中的特定時間的員工(S)。

+5

我知道這是不是一個答案,但是這看起來像一個可怕的桌子設計。 – 2014-09-23 12:43:42

+0

我看起來像你試圖做一些非常奇怪的事情,我建議你發佈整個方法,以便更容易找出你正在嘗試完成的事情 – Zache 2014-09-23 12:49:01

回答

1

您可以構建表達式樹來表示t他條件想手動,而不是使用一個lambda你正在試圖做的:

public static IQueryable<T> WhereEquals<T>(
    this IQueryable<T> query, 
    string property, 
    object valueToCompare) 
{ 
    var param = Expression.Parameter(typeof(T)); 
    var body = Expression.Equal(
     Expression.Property(param, property), 
     Expression.Constant(valueToCompare)); 
    var lambda = Expression.Lambda<Func<T, bool>>(body, param); 
    return query.Where(lambda); 
} 

這允許你寫:

var employeesOnCall = db.AdvOnCalls.WhereEquals(column, true) 
    .Select(adv => adv.ChartEmployee); 
+0

試過這個,但收到此錯誤:擴展方法必須定義在非泛型靜態類 – brown1455 2014-09-23 14:42:37

+0

@正如錯誤所述,您需要在非泛型靜態類中定義該方法。如果類是通用的,那麼它不是通用的,如果該類不是靜態的,則使其爲靜態。 – Servy 2014-09-23 14:43:13

+0

對不起!現在我收到此錯誤:[InvalidOperationException:二進制運算符Equal沒有爲類型System.Nullable'1 [System.Boolean]'和'System.Boolean'。]定義var body = Expression.Equal( – brown1455 2014-09-23 15:07:31

7

可怕的數據庫設計會導致一個可怕的解決方案:

where ((column == "AdvMonAM" && AdvMonAM == 1) 
     || (column == "AdvMonPM" && AdvMonPM == 1) 
    ) 

等等,每個字段添加一個條件。 (我不知道返回的數據類型。如果bool,刪除== 1。)

1

你可以使用Dynamic LINQ,使你做:

var column = "Adv" + dayOfWeek + time; 
var employeesOnCall = db.AdvOnCalls 
    .Where (column + " = 1") 
    .Select(x => x.ChartEmployee); 

...等。使用此功能

0
  • 一個選項

    var column = "Adv" + dayOfWeek + time; 
    var employeesOnCall = from r in db.AdvOnCalls 
             where GetPropByName(r, column) 
             select r.ChartEmployee; 
    

    :使用此功能

    var employeesOnCall = from r in db.AdvOnCalls 
             where columnSwitch(r, dayOfWeek, time) 
             select r.ChartEmployee; 
    

    bool GetPropByName(AdvOnCall item, string column) 
    { 
        return (bool)item.GetType().GetProperty(column).GetValue(item, null); 
    } 
    
  • 更好的選擇:)

    bool columnSwitch(AdvOnCall item, string dayOfWeek, string time) 
    { 
        if (time == "AM") 
         if (dayOfWeek == "Mon") 
          return item.AdvMonAM; 
         else if (dayOfWeek == "Tue") 
          return item.AdvTueAM; 
         ... 
        else // (time == "PM") 
         if (dayOfWeek == "Mon") 
          return item.AdvMonPM; 
         else if (dayOfWeek == "Tue") 
          return item.AdvTuePM; 
         ... 
    } 
    
+0

使用第一個選項時,我收到此錯誤:需要一個對象引用對於非靜態字段,方法或屬性'object.GetType()'\t return(bool)AdvOnCall.GetType()。GetProperty(column).GetValue(item,null); – brown1455 2014-09-23 13:56:15

+0

已將其更改爲item.GetType()和typeof(AdvOnCall)並收到運行時錯誤:[NotSupportedException:LINQ to Entities不能識別該方法'布爾GetPropByName(Intranet.Models.AdvOnCall,System.String)'方法,並且此方法無法翻譯成商店表達式。] – brown1455 2014-09-23 14:24:57

+0

@PatrickHofman,謝謝。我編輯。 – dovid 2014-09-23 14:30:51

2

如果數據庫中的列不能爲空:

string column = "Adv" + dayOfWeek + time; 
var employeesOnCall = from r in db.AdvOnCalls 
         where (bool)r[column] 
         select r.ChartEmployee; 

或:

string column = "Adv" + dayOfWeek + time; 
var employeesOnCall = from r in db.AdvOnCalls 
         where r.Field<bool>(column) 
         select r.ChartEmployee; 

如果列的值可以爲空:

string column = "Adv" + dayOfWeek + time; 
var employeesOnCall = from r in db.AdvOnCalls 
         where r.Field<bool?>(column)==true 
         select r.ChartEmployee; 
+0

不錯的選擇。順便說一下,'== true'是沒有必要的。 – 2014-09-23 13:56:37

+0

@PatrickHofman你是對的。我正在刪除它。另外,我假設它不是LinqToSql,AdvOnCalls是一個DataTable。如果它是LinqToSql,我將使用Reflection作爲lomed的解決方案 – Arie 2014-09-23 14:01:13

+0

據我所知,你不應該使用反射,因爲它會打破生成正確的SQL的可能性。它可能會導致數據庫上的大量負載處理客戶端上的所有內容。 – 2014-09-23 14:02:52