LINQKit
LINQKit copied to clipboard
Expression evaluation fails with nullables
trafficstars
Hi,
I have the expression builder method in VB.net
Public Shared Function CreateBaseFilter(Of returnType As PatientVisitBase)(appointmentId As String, patientId As String,
visitId As String, waitingRoomId As Integer?,
route As String, ticketNumber As Integer?) As ExpressionStarter(Of returnType)
Dim predicate = PredicateBuilder.[New](Of returnType)(True)
If Not String.IsNullOrEmpty(appointmentId) Then predicate = predicate.[And](Function(pvl) pvl.AppointmentId = appointmentId)
If Not String.IsNullOrEmpty(patientId) Then predicate = predicate.[And](Function(pvl) pvl.PatientId = patientId)
If Not String.IsNullOrEmpty(visitId) Then predicate = predicate.[And](Function(pv) pv.VisitId = visitId)
If waitingRoomId.HasValue Then predicate = predicate.[And](Function(pvl) **pvl.CentralWaitingRoomId IsNot Nothing AndAlso** pvl.CentralWaitingRoomId = waitingRoomId)
If Not String.IsNullOrEmpty(route) Then predicate = predicate.[And](Function(pvl) pvl.Route = route)
If ticketNumber.HasValue Then predicate = predicate.[And](Function(pvl) pvl.TicketNumber = ticketNumber)
Return predicate
End Function
Odd thing is that if pvl.CentralWaitingRoomId (int?) is null the predicate evaluation fails if I do not test for a null first (code in bold). This is odd as comparison of nullable types with a null should work.
Any suggestions?
As I am not really familiar with VB.NET, I translated your code to C# and tried to reproduce your problem using this:
public class PatientVisitBase
{
public string AppointmentId { get; set; }
public string PatientId { get; set; }
public string VisitId { get; set; }
public int? CentralWaitingRoomId { get; set; }
public string Route { get; set; }
public int? TicketNumber { get; set; }
}
public static ExpressionStarter<returnType> CreateBaseFilter<returnType>(string appointmentId, string patientId,
string visitId, int? waitingRoomId,
string route, int? ticketNumber)
where returnType : PatientVisitBase
{
var predicate = PredicateBuilder.New<returnType>(true);
if (!string.IsNullOrEmpty(appointmentId))
predicate = predicate.And(pvl => pvl.AppointmentId == appointmentId);
if (!string.IsNullOrEmpty(patientId))
predicate = predicate.And(pvl => pvl.PatientId == patientId);
if (!string.IsNullOrEmpty(visitId))
predicate = predicate.And(pvl => pvl.VisitId == visitId);
if (waitingRoomId.HasValue)
predicate = predicate.And(
pvl => pvl.CentralWaitingRoomId != null && pvl.CentralWaitingRoomId == waitingRoomId);
if (!string.IsNullOrEmpty(route))
predicate = predicate.And(pvl => pvl.Route == route);
if (ticketNumber.HasValue)
predicate = predicate.And(pvl => pvl.TicketNumber == ticketNumber);
return predicate;
}
[Theory]
[InlineData(null, null)]
[InlineData(null, 42)]
[InlineData(42, null)]
[InlineData(42, 42)]
public void Test(int? waitingRoomId, int? ticketNumber)
{
var expression = CreateBaseFilter<PatientVisitBase>(null, null, null, waitingRoomId, null, ticketNumber);
Assert.True(expression.Compile().Invoke(new PatientVisitBase
{
CentralWaitingRoomId = waitingRoomId,
TicketNumber = ticketNumber
}));
}
This seems to work as expected and the test succeeds. Can you give more details on your problem? How does the evaluation fail? Can you provide a minimal working example? There was no detail on PatientVisitBase in your code-snippet