2014-09-23 53 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