我希望得到所有参加过两场比赛之一的学生名单。这是我获得出席名单的功能:
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'.
答案 0 :(得分:1)
我没有编译器方便检查,但看起来你正在使用多行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))