我有以下IQueryable
:
IQueryable<Class1> queryable =
(from c1 in DbContext.Set<Class1>()
from c2 in DbContext.Set<Class2>()
from c3 in DbContext.Set<Class3>()
where c1.Id == c2.Class1Id
&& c2.Id == c3.Class2Id
&& c3.ValueAsString == val
select c1);
在上面的例子中,val是一个字符串。但是,Class3
还有其他几个成员:
public string ValueAsString { get;private set; }
public int? ValueAsInteger { get; set; }
public DateTime? ValueAsDate { get; set; }
public decimal? ValueAsDecimal { get; set; }
public bool? ValueAsBoolean { get; set; }
我需要修改IQueryable
,具体取决于'val'的类型,它可能是上述5种类型之一。是否可以将IQueryable
构造为:
IQueryable<Class1> queryable =
(from c1 in DbContext.Set<Class1>()
from c2 in DbContext.Set<Class2>()
from c3 in DbContext.Set<Class3>()
where c1.Id == c2.Class1Id
&& c2.Id == c3.Class2Id
select c1);
然后根据'val'的类型添加最终执行前的位置?例如,如果val是小数,则追加
c3.ValueAsDecimal == val
答案 0 :(得分:0)
对于您的任务来说,使用表达式而不是类似sql的linq会更方便。正如我所看到的,您的类通过主键相互连接,如果使用属性,此查询看起来大致如下:
Expression<Func<Class3, bool>> filterExpression = GetFilterExpression(val); //returns expression bases on val type
var queryable = DbContext.Set<Class1>()
.Include(cl1=>cl1.Class2.Class3) //or .Include(cl1=>cl1.Class2.Select(cl2=>cl2.Class3)) depending on your object relationships
.Where(filterExpression);
如果您需要为Class1类型的根实体加载Class2和Class3实例,则使用此处包含。如果您不需要它们,可以跳过.Include()结构。
GetFilterExpression示例:
public Expression<Func<Class1, bool>> GetFilterExpression(string value)
{
return cl1 => cl1.Class2.Class3.ValueAsString == value;
}
答案 1 :(得分:0)
这实际上很简单,你可以在条件通过时调用.Where(...)
。您只需预先选择所有值c1
,c2
和c3
,在添加.Where(...)
来电后,您可以选择c1
值从结果。像这样:
var q = (
from c1 in dbContext.Set<Class1>()
from c2 in dbContext.Set<Class2>()
from c3 in dbContext.Set<Class3>()
where c1.Id == c2.Class1Id
&& c2.Id == c3.Class2Id
select new { c1, c2, c3 }
);
object var = ...; // Some value
if (var is decimal)
{
q = q.Where(x => x.c3.ValueAsDecimal == (decimal)var);
}
else if (var is DateTime)
{
q = q.Where(x => x.c3.ValueAsDate == (DateTime)var);
}
// TODO: Add other types of 'var'
var queryable = q.Select(x => x.c1);