C# 在不使用PredicateBuilder的情况下向表达式动态添加谓词
我使用C# 在不使用PredicateBuilder的情况下向表达式动态添加谓词,c#,entity-framework,linq,entity-framework-6,linq-to-entities,C#,Entity Framework,Linq,Entity Framework 6,Linq To Entities,我使用linqToEntities,并希望动态添加或条件 我知道,它可以解决我的任务,但我不能使用它 我的情况如下: IEnumerable<Condition> conditions = new List<Condition>() { new Condition(){IdReference = 1, TableName = "Table1" }, new Condition(){IdReference = 2, TableName = "Table2"
linqToEntities
,并希望动态添加或
条件
我知道,它可以解决我的任务,但我不能使用它
我的情况如下:
IEnumerable<Condition> conditions = new List<Condition>()
{
new Condition(){IdReference = 1, TableName = "Table1" },
new Condition(){IdReference = 2, TableName = "Table2" },
new Condition(){IdReference = 3, TableName = "Table3" },
// and so on
};
if (conditions.Any())
{
var parameter = Parameter(typeof(History));
var body = conditions
.Select(condition => Expression.Constant(condition))
.Select(condition => Expression.AndAlso(
Expression.Equal(
Expression.PropertyOrField(parameter, nameof(History.IdReference)),
Expression.Convert(
Expression.PropertyOrField(condition, nameof(Condition.IdReference))
, Expression.PropertyOrField(parameter, nameof(History.IdReference)).Type)
),
Expression.Equal(
Expression.PropertyOrField(parameter, nameof(History.TableName)),
Expression.Convert(
Expression.PropertyOrField(condition, nameof(Condition.TableName))
, Expression.PropertyOrField(parameter, nameof(History.TableName)).Type)
)
))
.Aggregate(Expression.OrElse);
var predicate = Lambda<Func<History, bool>>(body, parameter);
histories = histories.Where(predicate);
}
IEnumerable条件=新列表()
{
新条件(){IdReference=1,TableName=“Table1”},
新条件(){IdReference=2,TableName=“Table2”},
新条件(){IdReference=3,TableName=“Table3”},
//等等
};
我得到的是:
var histories = db.History as IQueryable<History>;
foreach (var cond in conditions)
{
//What code should be here to be translated into:
/*
histories = histories
.Where(h => h.IdReference == 1 && h.TableName =="Table1"
|| h.IdReference == 2 && h.TableName == "Table2"
|| h.IdReference == 3 && h.TableName == "Table3");
// and so on
*/
}
var histories=db.History作为IQueryable;
foreach(条件中的var cond)
{
//这里应该翻译成什么代码:
/*
历史=历史
。其中(h=>h.IdReference==1&&h.TableName==“Table1”
||h.IdReference==2&&h.TableName==“Table2”
||h.IdReference==3&&h.TableName==“Table3”);
//等等
*/
}
但是,我事先不知道会有多少个条件。
如何从IEnumerable
动态添加或条件 我理解你的意思
var histories = db.History as IQueryable<History>;
foreach (var cond in conditions)
{
//What code should be here to be translated into:
histories = histories
.Where(h => h.IdReference == cond.IdReference &&
h.TableName ==cond.TableName );
}
var histories=db.History作为IQueryable;
foreach(条件中的var cond)
{
//这里应该翻译成什么代码:
历史=历史
其中(h=>h.IdReference==cond.IdReference&&
h、 TableName==cond.TableName);
}
不确定使用谓词生成器有什么问题-它不一定是LINQ Kit包,所谓的谓词生成器通常是一个带有两个扩展方法的单一静态类-like或my-ownPredicateUtils
from和类似
无论如何,一旦您想要它,当然可以使用简单的类静态方法来构建它
添加以下内容以避免在每次调用之前编写表达式。
:
using static System.Linq.Expressions.Expression;
然后用这样的方法:
IEnumerable<Condition> conditions = new List<Condition>()
{
new Condition(){IdReference = 1, TableName = "Table1" },
new Condition(){IdReference = 2, TableName = "Table2" },
new Condition(){IdReference = 3, TableName = "Table3" },
// and so on
};
if (conditions.Any())
{
var parameter = Parameter(typeof(History));
var body = conditions
.Select(condition => Expression.Constant(condition))
.Select(condition => Expression.AndAlso(
Expression.Equal(
Expression.PropertyOrField(parameter, nameof(History.IdReference)),
Expression.Convert(
Expression.PropertyOrField(condition, nameof(Condition.IdReference))
, Expression.PropertyOrField(parameter, nameof(History.IdReference)).Type)
),
Expression.Equal(
Expression.PropertyOrField(parameter, nameof(History.TableName)),
Expression.Convert(
Expression.PropertyOrField(condition, nameof(Condition.TableName))
, Expression.PropertyOrField(parameter, nameof(History.TableName)).Type)
)
))
.Aggregate(Expression.OrElse);
var predicate = Lambda<Func<History, bool>>(body, parameter);
histories = histories.Where(predicate);
}
if(conditions.Any())
{
var参数=参数(类型(历史));
变量体=条件
.Select(条件=>Expression.Constant(条件))
.Select(条件=>Expression.AndAlso(
表达式。相等(
Expression.PropertyOrField(参数,名称(History.IdReference)),
表达式。转换(
Expression.PropertyOrField(条件,名称(条件.IdReference))
,Expression.PropertyOrField(参数,名称(History.IdReference)).Type)
),
表达式。相等(
Expression.PropertyOrField(参数,nameof(History.TableName)),
表达式。转换(
Expression.PropertyOrField(条件,名称(条件.表名))
,Expression.PropertyOrField(参数,名称(History.TableName)).Type)
)
))
.聚合(表示为OrElse);
var谓词=Lambda(主体,参数);
历史=历史。其中(谓词);
}
如果没有太多的组合,只需使用一些条件:If(thisIsTheCase){histories=histories.Where(//put-your-conditions}否则If(另一种情况){histories=histories.Where(//put-your-conditions}
在覆盖所有情况之前,如果其他情况,请添加更多。您也可以通过创建动态表达式来完成,但这并不容易,因为您需要组合表达式。为什么不能使用PredicateBuilder
?@CodingYoshi,因为我的代码不会通过代码审阅。他在运行时之前不知道条件。这将导致正如我所理解的,他不知道历史列表中有多少个条件,但他在条件列表中有固定的条件,所以在条件列表中循环并比较!!正如我所想:)链接,其中s是和的等价物,而不是或。