Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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#_Linq_Lambda_Expression - Fatal编程技术网

C# LINQ的组合表达式

C# LINQ的组合表达式,c#,linq,lambda,expression,C#,Linq,Lambda,Expression,下面我有一个大的代码块,实际的代码并不是那么重要,但是为了演示我正在尝试做的事情,这里包含了一些代码 我有一个公共静态表达式>GetFreeSpotCount(…) 这个方法返回一个我想在另一个方法中重用的表达式 表达式本身返回一个数字,表示满足特定条件的[model]列表中[model]的数量 我希望新方法返回上面数字大于0的所有[model] 下面是我目前拥有的代码,我希望避免重复这么多代码 public static Expression<Func<ExamTimeSlot,

下面我有一个大的代码块,实际的代码并不是那么重要,但是为了演示我正在尝试做的事情,这里包含了一些代码

我有一个公共静态表达式>GetFreeSpotCount(…)

这个方法返回一个我想在另一个方法中重用的表达式

表达式本身返回一个数字,表示满足特定条件的[model]列表中[model]的数量

我希望新方法返回上面数字大于0的所有[model]

下面是我目前拥有的代码,我希望避免重复这么多代码

public static Expression<Func<ExamTimeSlot, int>> GetFreeSpotCountFor(List<Guid> drivingSchoolIds)
{
    return ets =>
    ets.Participants
        - ets.Exams.Where(ex => ex.Status == ExamStatus.Pending).Count(e => !ets.ExamTimeSlotReservations.Any(r => r.DrivingSchoolId == e.BookedByDrivingSchoolId))
        - ((int?)ets.ExamTimeSlotReservations.Sum(r => (ets.Exams.Where(ex => ex.Status == ExamStatus.Pending).Where(e => e.BookedByDrivingSchoolId == r.DrivingSchoolId).Count()
            - r.ReservedSpots) > 0 ? (ets.Exams.Where(ex => ex.Status == ExamStatus.Pending).Where(e => e.BookedByDrivingSchoolId == r.DrivingSchoolId).Count() - r.ReservedSpots) : 0) ?? 0)
        - ((int?)ets.ExamTimeSlotReservations.Sum(r => r.ReservedSpots) ?? 0)
        + ((((int?)ets.ExamTimeSlotReservations.Where(r => drivingSchoolIds.Any(id => r.DrivingSchoolId == id)).Sum(r => r.ReservedSpots) ?? 0)
            - ets.Exams.Where(ex => drivingSchoolIds.Any(id => ex.BookedByDrivingSchoolId == id) && ex.Status == ExamStatus.Pending).Count()) >= 0 ?
                (((int?)ets.ExamTimeSlotReservations.Where(r => drivingSchoolIds.Any(id => r.DrivingSchoolId == id)).Sum(r => r.ReservedSpots) ?? 0)
                - ets.Exams.Where(ex => drivingSchoolIds.Any(id => ex.BookedByDrivingSchoolId == id) && ex.Status == ExamStatus.Pending).Count())
                : 0);
}
公共静态表达式GetFreeSpotCountFor(列出驱动学校ID)
{
返回ets=>
ets.参与者
-ets.examts.Where(ex=>ex.Status==ExamStatus.Pending).Count(e=>!ets.ExamTimeSlotReservations.Any(r=>r.drivingschoolaid==e.bookedbydrivingschoolaid))
-((int?)ets.ExamTimeSlotReservations.Sum(r=>(ets.Exams.Where(ex=>ex.Status==ExamStatus.Pending)。其中(e=>e.BookedByDrivingSchoolId==r.DrivingSchoolId)。计数()
-r.ReservedSpots)>0?(ets.ex=>ex.Status==ExamStatus.Pending)。其中(e=>e.BookedByDrivingSchoolId==r.DrivingSchoolId)。Count()-r.ReservedSpots):0)??0)
-((int?)ets.ExamTimeSlotReservations.Sum(r=>r.ReservedSpots)??0)
+(((int?)ets.ExamTimeSlotReservations.Where(r=>drivingschoolaids.Any(id=>r.drivingschoolaid==id)).Sum(r=>r.ReservedSpots)??0)
-ets.Exams.Where(ex=>drivingschoolaids.Any(id=>ex.bookedbydrivingschoolaid==id)和&ex.Status==ExamStatus.Pending.Count())>=0?
((int?)ets.examTimesLotServations.Where(r=>DrivingSchoolId.Any(id=>r.DrivingSchoolId==id)).Sum(r=>r.ReservedSpots)??0)
-ets.Exams.Where(ex=>drivingschoolaids.Any(id=>ex.bookedbydrivingschoolaid==id)和&ex.Status==ExamStatus.Pending.Count())
: 0);
}
以及:

公共静态表达式GetExamTimeSlotsWithFreeSpotsFor(列出驱动学校ID)
{
返回ets=>
(ets.参与者
-ets.examts.Where(ex=>ex.Status==ExamStatus.Pending).Count(e=>!ets.ExamTimeSlotReservations.Any(r=>r.drivingschoolaid==e.bookedbydrivingschoolaid))
-((int?)ets.ExamTimeSlotReservations.Sum(r=>(ets.Exams.Where(ex=>ex.Status==ExamStatus.Pending)。其中(e=>e.BookedByDrivingSchoolId==r.DrivingSchoolId)。计数()
-r.ReservedSpots)>0?(ets.ex=>ex.Status==ExamStatus.Pending)。其中(e=>e.BookedByDrivingSchoolId==r.DrivingSchoolId)。Count()-r.ReservedSpots):0)??0)
-((int?)ets.ExamTimeSlotReservations.Sum(r=>r.ReservedSpots)??0)
+(((int?)ets.ExamTimeSlotReservations.Where(r=>drivingschoolaids.Any(id=>r.drivingschoolaid==id)).Sum(r=>r.ReservedSpots)??0)
-ets.Exams.Where(ex=>drivingschoolaids.Any(id=>ex.bookedbydrivingschoolaid==id)和&ex.Status==ExamStatus.Pending.Count())>=0?
((int?)ets.examTimesLotServations.Where(r=>DrivingSchoolId.Any(id=>r.DrivingSchoolId==id)).Sum(r=>r.ReservedSpots)??0)
-ets.Exams.Where(ex=>drivingschoolaids.Any(id=>ex.bookedbydrivingschoolaid==id)和&ex.Status==ExamStatus.Pending.Count())
: 0)) > 0;
}
我想做一些事情,比如:

public static Expression<Func<ExamTimeSlot, bool>> GetExamTimeSlotsWithFreeSpotsFor(List<Guid> drivingSchoolIds)
{
    return ets => GetFreeSpotCountFor(drivingSchoolIds) > 0;
}
公共静态表达式GetExamTimeSlotsWithFreeSpotsFor(列出驱动学校ID)
{
return ets=>GetFreeSpotCountFor(drivingschoolaids)>0;
}

我已经尝试在第一个表达式中使用Expression.GreaterThan,但由于我需要结果和[model],我无法找到一种方法使其工作。

为什么您特别希望组合表达式而不是组合查询调用?一种简单的方法是使GetExamTimeSlotsWithFreeSpots不获取并返回表达式,而是获取并返回查询,并向该查询添加两个where子句(每个都是存储的表达式)

public static IQueryable where examtimeslots with freespots for(IQueryable源代码,列出驱动学校ID)
{
var FirstFilter=GetFreeSpotCountFor(驾驶学校ID);
var SecondFilter=GetExamTimeSlotsWithFreeSpotsFor(驾驶学校ID);
返回源
.其中(第一个过滤器)
。其中(第二个过滤器);
}
这样您就不需要组合任何内容,让您的LINQ提供者自己组合这两个where子句


请注意,如果您真的想手动组合表达式,这是可能的,但据我所知,这将需要第三方API或直接使用表达式树(不仅仅是享受编译器为您提供的神奇功能)。如果只是返回一个包含2个表达式的表达式,并在表达式之间抛出and运算符,这并不难,但对于相同的结果来说,这似乎有些过分。

没有更简单的方法(没有第三方库)可以做到这一点。看起来我们应该很容易做到你所写的,但是我们被误导了,因为我们在创建表达式树时所依赖的语法糖

public static Expression<Func<ExamTimeSlot, bool>> GetExamTimeSlotsWithFreeSpotsFor(List<Guid> drivingSchoolIds)
{
    var param = Expression.Parameter(typeof(ExamTimeSlot));

    //We want to create a new lambda which will invoke `GetFreeSpotCountFor` with our parameter, and then check it's greater than 0
    var newBody = 
        Expression.GreaterThan(
            //View this as GetFreeSpotCountFor(drivingSchoolIds)(param) - where param will be given to us when this lambda is invoked
            Expression.Invoke(
                GetFreeSpotCountFor(drivingSchoolIds),
                param
            ),
            //Pass the right-hand value (0) to the GreaterThan check
            Expression.Constant(0)
        );

    var lambda = Expression.Lambda<Func<ExamTimeSlot, bool>>(newBody, param);
    return lambda;
}

您不应该使用`来转义代码(例如,对于文本块中的单个类名),而是使用正确的代码格式(每行用4个空格标识),这样我们从现在开始就可以获得正确的代码格式视图(将为您编辑它,但下次请记住它)啊stackoverflow速度的乐趣,其他人在最后13秒内修复了它。谢谢,我错过了关于缩进的部分,以后一定会使用它。我敢说,你需要进一步进行这项练习,并将看起来可怕的lambda的逻辑分解为更容易消化的块。我会非常担心这样一个完整的Winnebago逻辑的维护。令人惊讶的是,这完全如我所希望的那样解决了问题。在我尝试的时间里,我确实遇到了一些事情
  public static IQueryable<ExamTimeSlot> WhereExamTimeSlotsWithFreeSpotsFor (IQueryable<ExamTimeSlot> Source, List<Guid> drivingSchoolIds)
  {
       var FirstFilter = GetFreeSpotCountFor(drivingSchoolIds);
       var SecondFilter = GetExamTimeSlotsWithFreeSpotsFor(drivingSchoolIds);
       return Source
              .Where(FirstFilter)
              .Where(SecondFilter);                   
  }
public static Expression<Func<ExamTimeSlot, bool>> GetExamTimeSlotsWithFreeSpotsFor(List<Guid> drivingSchoolIds)
{
    var param = Expression.Parameter(typeof(ExamTimeSlot));

    //We want to create a new lambda which will invoke `GetFreeSpotCountFor` with our parameter, and then check it's greater than 0
    var newBody = 
        Expression.GreaterThan(
            //View this as GetFreeSpotCountFor(drivingSchoolIds)(param) - where param will be given to us when this lambda is invoked
            Expression.Invoke(
                GetFreeSpotCountFor(drivingSchoolIds),
                param
            ),
            //Pass the right-hand value (0) to the GreaterThan check
            Expression.Constant(0)
        );

    var lambda = Expression.Lambda<Func<ExamTimeSlot, bool>>(newBody, param);
    return lambda;
}
public static Expression<Func<ExamTimeSlot, bool>> GetExamTimeSlotsWithFreeSpotsFor(List<Guid> drivingSchoolIds)
{
    //This grabs the existing lambda, which we will work on
    var oldLambda = GetFreeSpotCountFor(drivingSchoolIds);
    var newBody = 
        //Invoke `GreaterThan` directly on the old lambda's Body
        Expression.GreaterThan(
            oldLambda.Body,
            //Pass the right-hand value (0) to the GreaterThan check
            Expression.Constant(0)
        );

    //Now, we need to pass in the old parameters, and build a new lambda.
    var lambda = Expression.Lambda<Func<ExamTimeSlot, bool>>(newBody, oldLambda.Parameters);
    return lambda;
}