LINQKit icon indicating copy to clipboard operation
LINQKit copied to clipboard

Expression evaluation fails with nullables

Open yvdh opened this issue 8 years ago • 1 comments
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?

yvdh avatar May 15 '17 15:05 yvdh

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

TheConstructor avatar Mar 20 '23 11:03 TheConstructor