Where Contains来自两个函数调用



我想获得参加两个活动之一的所有学生的列表。这是我获取考勤表的功能:

Private Function AttendanceList(ByVal Mode As AttendanceListLookupMode, ByVal AttendaceTypeID As Integer, ByVal EventID As Integer, ByVal EventOccurenceDate As Date) As IEnumerable(Of Integer)
        'Get the attendance table for specified event
        Dim resultSet = From a In db.tblAttendances
                        Where a.tblEventOccurence.EventID = EventID _
                            And a.tblEventOccurence.EventOccurenceDate = EventOccurenceDate
        'Apply mode filtering
        Select Case Mode
            Case AttendanceListLookupMode.AttendanceTypeIs
                resultSet = resultSet.Where(Function(x) x.tblAttendanceType.AttendanceTypeID = AttendaceTypeID)
            Case AttendanceListLookupMode.AttendanceTypeIsNot
                resultSet = resultSet.Where(Function(x) x.tblAttendanceType.AttendanceTypeID <> AttendaceTypeID)
        End Select
        'Return the student records
        Return resultSet.Select(Function(x) x.StudentID)
    End Function
    Private Enum AttendanceListLookupMode
        AttendanceTypeIs
        AttendanceTypeIsNot
    End Enum

现在我想在查询中使用它来检查是否有任何一个事件像这样参加:

'All students
                Dim resultSet = From s In db.tblStudents
                resultSet = resultSet.Where(Function(x)
                                                AttendanceList(AttendanceListLookupMode.AttendanceTypeIsNot,
                                                               CommonAttendanceTypeIDs.Absent,
                                                               CommonEventIDs.Learning,
                                                               ForDate).Contains(x.StudentID)
                                                Or 
                                                AttendanceList(AttendanceListLookupMode.AttendanceTypeIsNot,
                                                               CommonAttendanceTypeIDs.Absent,
                                                               CommonEventIDs.Basketball,
                                                               ForDate).Contains(x.StudentID)
                                            End Function)

当我试图编译这个时,我得到了这个错误:

Error   1   Overload resolution failed because no accessible 'Where' can be called with these arguments:
Extension method 'Public Function Where(predicate As System.Linq.Expressions.Expression(Of System.Func(Of tblStudent, Integer, Boolean))) As System.Linq.IQueryable(Of tblStudent)' defined in 'System.Linq.Queryable': Nested function does not have a signature that is compatible with delegate 'System.Func(Of tblStudent, Integer, Boolean)'.
Extension method 'Public Function Where(predicate As System.Linq.Expressions.Expression(Of System.Func(Of tblStudent, Boolean))) As System.Linq.IQueryable(Of tblStudent)' defined in 'System.Linq.Queryable'.
Extension method 'Public Function Where(predicate As System.Func(Of tblStudent, Integer, Boolean)) As System.Collections.Generic.IEnumerable(Of tblStudent)' defined in 'System.Linq.Enumerable': Nested function does not have a signature that is compatible with delegate 'System.Func(Of tblStudent, Integer, Boolean)'.
Extension method 'Public Function Where(predicate As System.Func(Of tblStudent, Boolean)) As System.Collections.Generic.IEnumerable(Of tblStudent)' defined in 'System.Linq.Enumerable'.

我没有方便检查的编译器,但看起来您使用的是多行lambda语法,但指定了一个空表达式。编译器不会喜欢这样,它需要一个语句,而不是表达式。这两种语法的区别如下:

Dim singleLinelambda = Function(x) x + 1
Dim multiLineLambda = Function(x)
                          Return x + 1
                      End Function

试试这个:

resultSet = resultSet.Where(Function(x)
    Return AttendanceList(AttendanceListLookupMode.AttendanceTypeIsNot,
        CommonAttendanceTypeIDs.Absent,
        CommonEventIDs.Learning,
        ForDate).Contains(x.StudentID) Or
        AttendanceList(AttendanceListLookupMode.AttendanceTypeIsNot,
        CommonAttendanceTypeIDs.Absent,
        CommonEventIDs.Basketball,
        ForDate).Contains(x.StudentID)
    End Function)

就我个人而言,我会将lambda主体移动到一个带有参数的单独方法中。它将使代码更可读,例如

Private Function MyPredicate(Mode As AttendanceListLookupMode, AttendaceTypeID As Integer, EventID1 As Integer, EventID2 As Integer, EventOccurenceDate As Date, StudentID As Integer) As Boolean
    Return AttendanceList(Mode,
        AttendaceTypeID,
        EventID1,
        EventOccurenceDate).Contains(StudentID) Or
        AttendanceList(Mode,
        AttendaceTypeID,
        EventID2,
        EventOccurenceDate).Contains(StudentID)
End Function
' Usage...
resultSet = resultSet.Where(Function(x) MyPredicate(
    AttendanceListLookupMode.AttendanceTypeIsNot,
    CommonAttendanceTypeIDs.Absent,
    CommonEventIDs.Learning,
    CommonEventIDs.Basketball,
    ForDate,
    x.StudentID))

最新更新