C# C-如何在LINQ where中使用带参数的表达式

C# C-如何在LINQ where中使用带参数的表达式,c#,sql,linq,.net-core,ef-core-3.0,C#,Sql,Linq,.net Core,Ef Core 3.0,任务:我需要在LINQ中提供一些带参数的表达式,从数据库中获取一些数据,但上面有一个错误 此工作表达式示例: var shopExp = GetPersonForShop(PersonTypeIds.Director, new Guid("adda423f-8c38-40e0-9f39-6deceb787bc0")); // id Where(shopExp) 但我需要动态分配id,但上面出现错误: _repository.Persons .Where(GetPersonForShop(Pe

任务:我需要在LINQ中提供一些带参数的表达式,从数据库中获取一些数据,但上面有一个错误 此工作表达式示例:

var shopExp = GetPersonForShop(PersonTypeIds.Director, new Guid("adda423f-8c38-40e0-9f39-6deceb787bc0")); // id
Where(shopExp) 
但我需要动态分配id,但上面出现错误:

_repository.Persons
.Where(GetPersonForShop(PersonTypeIds.Director, person.PersonId)
并得到错误:

{无法将类型为'System.Linq.Expressions.InstanceMethodCallExpression2'的对象强制转换为类型为'System.Linq.Expressions.LambdaExpression'

LINQ的功能如何:

private Expression<Func<Person, bool>> GetPersonForShop(PersonTypeIds personTypeId, Guid personId)
        {
            return person => person .PeronTypeId== (int) personTypeId && person .PersonId == personId;
        }
这是一个近似的产品,只需更改参数代码的名称即可

如何将带参数的表达式添加到Where子句???

Lambda表达式使用=>表示法。试着这样做:

var idToFind = new Guid("adda423f-8c38-40e0-9f39-6deceb787bc0");

var result = _repository.Persons
    .Where(p => p.TypeId == PersonTypeIds.Director && p.PersonId == idToFind);
在此表达式中,p表示Persons表中的每个Person记录,并使用其后的布尔表达式逐个进行比较

根据您的数据源,每个p的比较要么由内存中的.NET完成,要么在数据库中使用由布尔表达式构造的SQL WHERE子句进行。最后一种方法是最佳的,因为这意味着在进行比较之前,不必将整个Persons表转移到.NET内存中

更新-要多次应用相同的条件而不在代码中重复,同时保持LINQ到SQL转换的优点不变,可以将该条件放入表达式对象中,然后多次使用该条件:

Expression<Func<Person, bool>> expression =
    p => p.TypeId == PersonTypeIds.Director && p.PersonId == idToFind;

var result1 = datasource1.Where(expression);
var result2 = datasource2.Where(expression);
var result3 = datasource3.Where(expression);
或者通过生成表达式对象的方法:

var result1 = datasource1.Where(GetExpression(idToFind));
var result2 = datasource2.Where(GetExpression(idToFind));
var result3 = datasource3.Where(GetExpression(idToFind));

public Expression<Func<Person, bool>> GetExpression(Guid idToFind)
{
    return p => p.TypeId == PersonTypeIds.Director && p.PersonId == idToFind;
}
或者,您也可以使用助手方法:

var result1 = FilterByTypeAndId(datasource1, idToFind);
var result2 = FilterByTypeAndId(datasource2, idToFind);
var result3 = FilterByTypeAndId(datasource3, idToFind);

public IQueryable<Person> FilterByTypeAndId(IQueryable<Person> datasource, Guid idToFind)
{
    return datasource.Where(p => p.TypeId == PersonTypeIds.Director && p.PersonId == idToFind);
}

根据前面的回答,我将给你一些选择和建议

var idToFind = new Guid("adda423f-8c38-40e0-9f39-6deceb787bc0");

var result = _repository
    .Persons
    .Where(p => p.TypeId == PersonTypeIds.Director)
    .Where(p => p.PersonId == idToFind)
    .ToList();

首先是分两步执行where子句,然后添加ToList,使用ToList,您将处理非常有用的集合和LINQ。通过分两步执行where子句,更便于阅读。

GetPersonForShop的签名是什么?EF/EF核心已经允许动态查询。有多个答案显示了如何动态添加Where子句。我怀疑真正的问题是在EF上添加了一个通用存储库,并失去了执行LINQ查询的能力。我添加了有关此任务的更多信息。是的,我知道lambda是如何工作的,我需要将expressionthe返回带参数的表达式的函数移动到'where'linq方法中。我很困惑。首先使用GetPersonForShop,然后向我们展示具有相同外观签名的GetKpisForEntity方法。您是否只是混淆了这两个方法名称?您的代码中也有很多拼写错误,这使得我们无法判断您是在编写问题时还是在编写代码时犯了这些错误。从我所能得到的情况来看,这应该对您有所帮助:[ref]这个问题在代码中的11个位置重复,这就是为什么我想使用表达式来简化它。此外,我有更复杂的选择逻辑,但不能使用,因为我想使用没有参数的表达式