Где содержится из двух вызовов функций - PullRequest
1 голос
/ 12 января 2012

Я хочу получить список всех студентов, которые были на одном из двух мероприятий.Вот моя функция для получения списка посещаемости:

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'.

1 Ответ

1 голос
/ 12 января 2012

У меня нет удобной проверки компилятора, но похоже, что вы используете многострочный лямбда-синтаксис, но задаете голое выражение. Компилятору это не понравится, он ожидает утверждения, а не выражения. Два синтаксиса отличаются следующим образом:

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)

Лично я бы переместил лямбда-тело в отдельный метод с параметрами. Это сделало бы код более читабельным, например,

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))
...