C# 使用表达式树创建动态LINQ查询
我无法复制多个。在我的使用表达式树的linq查询中,我需要此查询是动态的,因为它是一个搜索功能。我最终要查询的数据库将变大,因此我需要高效且无法筛选客户端。我至少试着从其中3列开始过滤。下面我添加了三个我试图过滤的ID。我已经阅读了很多关于表达式树的内容,但是我需要一些人的帮助来将它们应用到我所做的事情中,因为它们让我感到困惑C# 使用表达式树创建动态LINQ查询,c#,sql,linq,C#,Sql,Linq,我无法复制多个。在我的使用表达式树的linq查询中,我需要此查询是动态的,因为它是一个搜索功能。我最终要查询的数据库将变大,因此我需要高效且无法筛选客户端。我至少试着从其中3列开始过滤。下面我添加了三个我试图过滤的ID。我已经阅读了很多关于表达式树的内容,但是我需要一些人的帮助来将它们应用到我所做的事情中,因为它们让我感到困惑 public int? heightId { get; set; } public int? ageId { get; set; } public
public int? heightId { get; set; }
public int? ageId { get; set; }
public int? genderId { get; set; }
它不是动态的,因为您预先知道列。您也不需要使用表达式树。您可以有条件地应用过滤器:
public Class[] FindByFilter(int limit, int? heightId = null, int? ageId = null, int? genderId = null)
{
var classes = databaseContext.Set<Class>();
if (heightId.HasValue)
classes = classes.Where(c => c.HeightId == heightId.Value);
if (ageId.HasValue)
classes = classes.Where(c => c.AgeId == ageId.Value);
if (heightId.HasValue)
classes = classes.Where(c => c.GenderId == genderId.Value);
return classes.Take(limit).ToArray();
}
public类[]FindByFilter(int-limit,int-heightId=null,int-ageId=null,int-genderId=null)
{
var classes=databaseContext.Set();
if(heightId.HasValue)
class=classes.Where(c=>c.HeightId==HeightId.Value);
if(ageId.HasValue)
class=classes.Where(c=>c.AgeId==AgeId.Value);
if(heightId.HasValue)
class=classes.Where(c=>c.GenderId==GenderId.Value);
返回类.Take(limit).ToArray();
}
因此,现在FindByFilter(10,1,null,2)
或等效的FindByFilter(10,heightId:1,genderId:2)
将返回前10行,高度为1,性别为2,但不包括任何年龄 所以您有一个(或几个)属性数量有限的类,可能少于100个
在代码的某个地方,这可能在用户界面中,但也可能是在读取internet页面、文件或从数据库获取信息之后,在代码的某个地方,您将有一些输入,您可以从中决定必须在哪里执行
因此,在代码中的某个地方,有一个函数,它接受一些输入并返回表达式,其中:
Expression<Func<MyTable, bool>> CreateExpression(MyInput input) {...}
如果你选择这样的投入,你的生活会变得非常困难。您几乎必须为此构建某种编译器,检查各种错误输入。您必须检测运算符何时表示属性,何时表示操作或比较器。不容易做到
如果您真的希望有可能组合表达式,请考虑使用用户界面元素,如组合框,用户必须选择一个属性,并键入正确的值类型。p>
因为属性的数量是有限的,所以可以使用上面的过程来创建表达式。组合如下所示:
ExpressionFunc<TSource, bool>> CreateAnd<TSource>(
Expression<Func<TSource, bool>> X,
Expression<Func<TSource, bool>> Y)
{
return (sourceElement) => X(sourceElement) && Y(sourceElement);
}
ExpressionFunc>CreateAnd(
表达式X,
表达式(Y)
{
返回(sourceElement)=>X(sourceElement)和&Y(sourceElement);
}
再次强调:即使你想让操作符组合语句,如果你使用组合框或类似的,你也不能得到错误的输入,而且组合的数量也是相当有限的
结论
虽然可以从字符串输入创建表达式,但这意味着您必须创建一个类似于编译器的东西来检查错误的输入。这不容易理解、测试和维护
作为请求的数量,其中语句是相当有限的,可能小于100,考虑使用具有大切换情况的函数
为什么需要表达式树?如果您在设计时知道这三列是什么,为什么不能在这三列上使用Where
。@YeldarKurmangaliyev因为用户可以选择是否使用该功能进行搜索,所以并非所有三列都会被选作搜索选项。我希望第一次这样做是有意义的。但是从数据库中点击pull的Where()呢?我想先构建查询,然后再查询database@Yaboy93否,查询将仅作为单个查询在.ToArray()
上编译和执行,并应用所有指定的。其中
条件。您可能想阅读更多关于thank You@YeldarKurmangaliyev的信息,所以请确保在阅读本文后,查询实际上只在您实际请求正确数据时执行,因此点击.ToArray()或ToList()会触发db检索?因此,理想情况下,在调用db correct之前,您可以有20个位置来尽可能多地过滤数据?@Yaboy93:)只有在您枚举查询时,才会构建和执行查询。它可以.ToArray()
,.ToList()
甚至foreach
。
"HeightId == 4 AND AgeId == 10 OR ..."
ExpressionFunc<TSource, bool>> CreateAnd<TSource>(
Expression<Func<TSource, bool>> X,
Expression<Func<TSource, bool>> Y)
{
return (sourceElement) => X(sourceElement) && Y(sourceElement);
}