我想获得参加两个活动之一的所有学生的列表。这是我获取考勤表的功能:
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))