动态构建IQueryable
本文关键字:IQueryable 构建 动态 | 更新日期: 2023-09-27 18:23:43
我有以下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; }
我需要根据"val"的类型修改IQueryable
,它可能是上面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
对于您的任务来说,使用表达式而不是像linq这样的sql会更方便。正如我所看到的,你的类通过主键相互连接,如果使用属性,这个查询可以大致如下所示:
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实例,则使用此处的Includes。如果你不需要它们,你可以跳过.Include()构造。
GetFilterExpression示例:
public Expression<Func<Class1, bool>> GetFilterExpression(string value)
{
return cl1 => cl1.Class2.Class3.ValueAsString == value;
}
这实际上很容易,当条件通过时,您只需调用.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);