JSON
JSON

Reputation: 1623

How to handle null values with where clause in LINQ?

I have two entities where I Groupjoin them into a list and I am trying to search for a match for a certain value in different properties. The problem is that if one property has null value in the list, the search completly ignores the other properties and returns empty list.

I am posting the relevant code,

populating entities,

List<PatientsRegistrySearchViewModel> SearchList = new List<PatientsRegistrySearchViewModel>(); 
List<PatientsRegistrySearchViewModel> DataResponse = new List<PatientsRegistrySearchViewModel>();

Groupjoin,

SearchList = (
    from p in registryList
    join c in registryAccountsList on p.PatientFileId equals c.PatientFileId into g
    from c in g.DefaultIfEmpty()
    select new PatientsRegistrySearchViewModel {
        PatientFileId = p.PatientFileId,
        Name = p.FirstName,
        AliasName = p.AliasName,
        PatientDob = p.PatientDob.ToString(),
        PatientAge = 0,
        PatientEmail = c?.Email,
        SocialSecurityNo = p.SocialSecurityNo,
        PatientMobileNo = c?.MobileNo
    }).ToList();

and my search logic,

searchResults = (from i in SearchList where (
    i.Name.ToLower().Contains (value.ToLower()) ||
    i.PatientEmail.ToLower ().Contains (value.ToLower())
) select i).ToList();

this search logic will compare the value to Name or PatientEmail, if either prop is null in the list, the returned result is empty! Why (||) "or" operator is not skipping null?

list example,

{
patientFileId: 1111,
Name: "John",
aliasName: null,
patientDob: "1/25/85 12:00:00 AM",
patientAge: 0,
patientEmail: "[email protected]",
socialSecurityNo: "1212121SSN",
patientMobileNo: "3244990"
},
{
patientFileId: 2222,
Name: "Nicole",
aliasName: null,
patientDob: "1/1/01 12:00:00 AM",
patientAge: 0,
patientEmail: null,
socialSecurityNo: null,
patientMobileNo: null
},
{
patientFileId: 3333,
Name: "Nancy",
aliasName: null,
patientDob: "3/25/85 12:00:00 AM",
patientAge: 0,
patientEmail: "[email protected]",
socialSecurityNo: null,
patientMobileNo: "3244990"
}

Upvotes: 0

Views: 5945

Answers (3)

Chrᴉz remembers Monica
Chrᴉz remembers Monica

Reputation: 1904

Ok, I made a small test which made my guess sure. Code snippet:

class Program
{
    static void Main(string[] args)
    {
        var searchList = new List<TwoProps>()
        {
            new TwoProps() {Name = "sdfs1", PatientEmail="[email protected]" },
            new TwoProps() {Name = "sdfs2", PatientEmail=null },
            new TwoProps() {Name = "sdfs3", PatientEmail="[email protected]" }
        };

        var stringToSearch = "myMail".ToLower();
        var query = (from listItem in searchList
                    where listItem.Name.ToLower().Contains(stringToSearch)
                        || listItem.PatientEmail.ToLower().Contains(stringToSearch)
                    select listItem).ToList(); //NullReferenceException is thrown here @ second element
        //listItem.PatientEmail.ToLower() => null.ToLower() => NRE

        Console.WriteLine(query.Count());
    }

    private class TwoProps
    {
        public string Name { get; set; }
        public string PatientEmail { get; set; }
    }
}

You can fix this with ...|| (listItem.PatientEmail?.ToLower().Contains(stringToSearch) ?? false).

As expected, there is a NRE thrown. You are handling the exception somewhere and return a empty list or simply dont populate your list with teh result items(results are the same).

Upvotes: 2

Jamez Fatout
Jamez Fatout

Reputation: 392

For example:

AliasName = p.AliasName,

Replace With

AliasName = p.AliasName ?? ""

When p.AliasName is null, then AliasName is an empty string.

Upvotes: 1

Shaun
Shaun

Reputation: 31

The || operator plus the String.IsNullOrWhiteSpace will INCLUDE values that are null. And then you are trying to do a ToLower() on a null value.

Try this. It will first make sure the valie of email is not null then do the contains.

searchResults = (from i in SearchList where (
    i.Name.ToLower ().Contains (value.ToLower ()) ||
    (!string.IsNullOrWhiteSpace (i.PatientEmail) &&
    i.PatientEmail.ToLower ().Contains (value.ToLower ()))
) select i).ToList ();

Upvotes: 1

Related Questions