Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在LinQ表达式树中声明变量_C#_.net_Linq_Lambda_Expression - Fatal编程技术网

C# 在LinQ表达式树中声明变量

C# 在LinQ表达式树中声明变量,c#,.net,linq,lambda,expression,C#,.net,Linq,Lambda,Expression,在前面的问题()中,我通过使用let语句声明变量来解决问题,我的代码如下所示: return from q in pList let currentContract = q.StaffContracts.OrderByDescending(p => p.SignedDate).Where(p => p.Active).FirstOrDefault() where (currentContract.Timespan >= fromValue && currentC

在前面的问题()中,我通过使用
let
语句声明变量来解决问题,我的代码如下所示:

return
from q in pList
let currentContract = q.StaffContracts.OrderByDescending(p => p.SignedDate).Where(p => p.Active).FirstOrDefault()
where (currentContract.Timespan >= fromValue && currentContract.Timespan <= toValue)
select q;
编译错误消息为:

具有语句体的lambda表达式无法转换为表达式树


有什么解决方法吗?

恐怕您必须使用
System.Linq.Expressions.expression
类方法手动准备表达式:

public static Expression<Func<Item, bool>> GetWhere(TimeSpan fromValue, TimeSpan toValue)
{
    Expression<Func<Item, Contract>> currentContract =
        q => q.StaffContracts
              .OrderByDescending(p => p.SignedDate)
              .Where(p => p.Active)
              .FirstOrDefault();

    var param = currentContract.Parameters.First();

    return Expression.Lambda<Func<Item, bool>>(
                Expression.And(
                    Expression.And(
                        Expression.NotEqual(
                            currentContract,
                            Expression.Constant(null, typeof(Contract))),
                        Expression.GreaterThanOrEqual(
                            Expression.Property(currentContract, "Timespan"),
                            Expression.Constant(fromValue))),
                    Expression.LessThanOrEqual(
                        Expression.Property(currentContract, "Timespan"),
                        Expression.Constant(toValue))),
                param);
}
公共静态表达式GetWhere(TimeSpan-fromValue,TimeSpan-toValue)
{
表达合同=
q=>q.员工合同
.OrderByDescending(p=>p.SignedDate)
.其中(p=>p.Active)
.FirstOrDefault();
var param=currentContract.Parameters.First();
返回表达式.Lambda(
表达。及(
表达。及(
表达式。NotEqual(
当前合同,
表达式.Constant(null,typeof(Contract)),
表达式。大于或等于(
表达式.属性(当前合同,“时间跨度”),
表达式.常量(fromValue)),
Expression.LessThanOrEqual(
表达式.属性(当前合同,“时间跨度”),
表达式.常量(toValue)),
参数);
}

恐怕您必须使用
System.Linq.Expressions.expression
类方法手动准备表达式:

public static Expression<Func<Item, bool>> GetWhere(TimeSpan fromValue, TimeSpan toValue)
{
    Expression<Func<Item, Contract>> currentContract =
        q => q.StaffContracts
              .OrderByDescending(p => p.SignedDate)
              .Where(p => p.Active)
              .FirstOrDefault();

    var param = currentContract.Parameters.First();

    return Expression.Lambda<Func<Item, bool>>(
                Expression.And(
                    Expression.And(
                        Expression.NotEqual(
                            currentContract,
                            Expression.Constant(null, typeof(Contract))),
                        Expression.GreaterThanOrEqual(
                            Expression.Property(currentContract, "Timespan"),
                            Expression.Constant(fromValue))),
                    Expression.LessThanOrEqual(
                        Expression.Property(currentContract, "Timespan"),
                        Expression.Constant(toValue))),
                param);
}
公共静态表达式GetWhere(TimeSpan-fromValue,TimeSpan-toValue)
{
表达合同=
q=>q.员工合同
.OrderByDescending(p=>p.SignedDate)
.其中(p=>p.Active)
.FirstOrDefault();
var param=currentContract.Parameters.First();
返回表达式.Lambda(
表达。及(
表达。及(
表达式。NotEqual(
当前合同,
表达式.Constant(null,typeof(Contract)),
表达式。大于或等于(
表达式.属性(当前合同,“时间跨度”),
表达式.常量(fromValue)),
Expression.LessThanOrEqual(
表达式.属性(当前合同,“时间跨度”),
表达式.常量(toValue)),
参数);
}

因此,我们可以在这里创建一个
Compose
方法,该方法采用一个
表达式
,表示一个具有一个参数和一个返回值的lambda,然后采用第一个lambda的输出作为输入的第二个lambda,然后返回一个新的lambda,该lambda接受第一个参数的输入并返回第二个参数的输出

如果它只是常规委托,那么该方法看起来会像这样(只是为了让您了解它在概念上的作用):

这使用以下方法将一个
表达式的所有实例替换为另一个

internal class ReplaceVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}

public static Expression Replace(this Expression expression,
    Expression searchEx, Expression replaceEx)
{
    return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
现在我们有了
Compose
方法,我们可以编写一个表达式,它接受您的一项并返回一个
契约
,然后编写另一个方法,接受该契约并计算一个
bool
,指示它是否有效:

public static Expression<Func<Item, bool>> GetFilter(
    TimeSpan fromValue, TimeSpan toValue)
{
    Expression<Func<Item, Contract>> currentContract =
        q => q.StaffContracts
                .OrderByDescending(p => p.SignedDate)
                .Where(p => p.Active)
                .FirstOrDefault();

    return currentContract.Compose(contract =>
        contract != null &&
        contract.TimeSpan >= fromValue &&
        contract.TimeSpan <= toValue);
}
公共静态表达式GetFilter(
TimeSpan fromValue,TimeSpan toValue)
{
表达合同=
q=>q.员工合同
.OrderByDescending(p=>p.SignedDate)
.其中(p=>p.Active)
.FirstOrDefault();
返回currentContract.Compose(合同=>
合同!=null&&
contract.TimeSpan>=fromValue&&

contract.TimeSpan因此,我们可以在这里创建一个
Compose
方法,该方法使用一个
表达式
表示一个lambda,其中包含一个参数和一个返回值,然后使用第一个lambda的输出作为输入,然后返回一个新的lambda,该lambda接受第一个参数的输入并返回second参数的输出

如果它只是常规委托,那么该方法看起来会像这样(只是为了让您了解它在概念上的作用):

这使用以下方法将一个
表达式的所有实例替换为另一个

internal class ReplaceVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}

public static Expression Replace(this Expression expression,
    Expression searchEx, Expression replaceEx)
{
    return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
现在我们有了
Compose
方法,我们可以编写一个表达式,它接受您的一项并返回一个
契约
,然后编写另一个方法,接受该契约并计算一个
bool
,指示它是否有效:

public static Expression<Func<Item, bool>> GetFilter(
    TimeSpan fromValue, TimeSpan toValue)
{
    Expression<Func<Item, Contract>> currentContract =
        q => q.StaffContracts
                .OrderByDescending(p => p.SignedDate)
                .Where(p => p.Active)
                .FirstOrDefault();

    return currentContract.Compose(contract =>
        contract != null &&
        contract.TimeSpan >= fromValue &&
        contract.TimeSpan <= toValue);
}
公共静态表达式GetFilter(
TimeSpan fromValue,TimeSpan toValue)
{
表达合同=
q=>q.员工合同
.OrderByDescending(p=>p.SignedDate)
.其中(p=>p.Active)
.FirstOrDefault();
返回currentContract.Compose(合同=>
合同!=null&&
contract.TimeSpan>=fromValue&&

contract.TimeSpan尝试从此[此处链接][1][1]获取更多信息:尝试从此[此处链接][1][1]获取更多信息:您正在对
currentContract
执行操作,就好像它是一个
Contract
对象一样,但它不是。它是一个表示获取函数的表达式,因此您的代码无法工作。也许您是想获取该表达式的主体?我没有测试它,但我希望它与
return q=>q.StaffContracts.orderByDescent相同ing(p=>p.SignedDate).Where(p=>p.Active).FirstOrDefault()!=null&&q.StaffContracts.OrderByDescending(p=>p.SignedDate).Where(p=>p.Active).FirstOrDefault().Timespan>fromValue&&q.StaffContracts.OrderByDescending(p=>p.SignedDate).Where(p=>p.Active).FirstOrDefault().Timespan
,这就是我希望它能工作的原因。但它不会成功