-1

I have the following linq query:

private List<Port> DoCountriesSearch(string search)
{
    return Countries.Where(x => x.CountrySearch.ToLower().Contains(search.ToLower())).ToList();
}

I have an object called Countries which is a list of Port objects with various properties. Each Port object contains a property called CountrySearch which you can see here:

enter image description here

But as soon as I try to run the linq query on Countries, suddenly the CountrySearch property is null which throws a null reference exception:

enter image description here

I've never had this issue with linq before. What am I missing?

Guitrum
  • 171
  • 1
  • 10
  • 1
    Please [edit] your post with a [mre]. – gunr2171 Nov 24 '22 at 17:34
  • 3
    The screenshots show different instances. "Germany" instance having non-nullable `CountrySearch` does not prove that "New Caledonia" will have it too. – Guru Stron Nov 24 '22 at 17:36
  • 1
    Is `Countries` an in-memory list or a DbSet? If it's a list you can use the case-invariant version of Contains, eg `Where(x => x.CountrySearch.Contains(search,StringComparions.OrdinalIgnoreCase))`. Each call to `ToLower()` creates a new temporary string instance that has to be garbage-collected – Panagiotis Kanavos Nov 24 '22 at 17:39
  • @GuruStron the screenshots were just meant to illustrate the problem. this field will never be null no matter the instance. – Guitrum Nov 24 '22 at 18:02
  • This query does not make anything `null`. The `null` entries must have been there in the `Countries` list already. It would help to see how you are filling this list. – Olivier Jacot-Descombes Nov 24 '22 at 18:28
  • @OlivierJacot-Descombes I load a DataTable object from a database query (at this point the CountrySearch value exists since it is returned as part of the query). I then have a method that iterates over the DataTable rows and reads the values in to their corresponding fields in the Port object eventually returning a list of Port objects. – Guitrum Nov 24 '22 at 18:36
  • The problem is probably in the *"method that iterates over the DataTable rows and reads the values in to their corresponding fields in the Port object"*. Please show us this method! – Olivier Jacot-Descombes Nov 24 '22 at 18:57
  • I figured out the issue! i posted an answer explaining what happened. Thanks for helping me arrive at the solution @OlivierJacot-Descombes – Guitrum Nov 24 '22 at 18:59

2 Answers2

0

Your list has a lot of entries. In some entries CountrySearch is not null, in others it is null. There is no magic happening with LINQ here.

You can fix this with a Null-conditional operator

private List<Port> DoCountriesSearch(string search)
{
    return Countries.Where(
        x => x.CountrySearch?.Contains(
            search,
            StringComparions.CurrentCultureIgnoreCase) == true
    ).ToList();
}

Note that == true is required here because we have to cope with null values.

See also:

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • This field will never be null. Each entry will always have a value since it comes straight from the database query for a non-nullable field. – Guitrum Nov 24 '22 at 18:08
  • *"This field will never be null."*, well it is null obviously for "New Caledonia". This `null` value was there before executing this query, because this query isn't changing any fields or properties of existing objects. How is the `Countries` list created or filled? This is most probably the place where the things go wrong. – Olivier Jacot-Descombes Nov 24 '22 at 18:32
0

The issue was entirely my fault. I had a buried method that was appending Port objects to the bottom of the list that did not come from the database, therefore the CountrySearch fields for those items were indeed null.

Guitrum
  • 171
  • 1
  • 10