-1

I am new to Linq and Entity Framework, and am receiving a null reference exception on this query:

using (var db = new PhoenixContext())
{
    tblCustomer cust = (from c in db.tblCustomer
                        where c.CustomerID == _CustomerID
                        select c).FirstOrDefault();

    string altPhone;
    altPhone = cust.tblCustomerContactInformation1.tblCustomerContactInformationPhone.Where(p => p.PhoneTypeID == 2).FirstOrDefault().Phone;
)

There is a single row in tblCustomerContactInformationPhone. The Where clause should remove it, and I should end up getting an empty string. However, instead I receive:

Object reference not set to an instance of an object.

What am I doing wrong, and how do I do this correctly so that an empty result set is properly converted to an empty string?

The linked question is not helpful, as this is specific to the use of Linq, which that question does not cover. @evanmcdonnal's answer was quite helpful, and solved my problem.

Dave Johnson
  • 825
  • 16
  • 27
  • please show all relevant code meaning how cust is defined and or all other objects that you are declaring.. you can't Declare an instance of an object for example `MyObject myobject;` and expect to gain access and or assigne values to any of it's fields or property's without `Nweing` the object.. do a google search on examples on how to instantiate Object references – MethodMan Apr 27 '15 at 21:05
  • `.FirstOrDefault()` returns `null` if no rows are returned. You can't access `null.Phone`. – Blorgbeard Apr 27 '15 at 21:07
  • possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Blorgbeard Apr 27 '15 at 21:08
  • I have tried several things to get around this fact. Including `??` and explicitly checking for `null` (if (... != null)). – Dave Johnson Apr 27 '15 at 21:12
  • @DaveJohnson: What do you see when you step through the debugger and check the values of your various variables and expressions? One of them is null. – StriplingWarrior Apr 27 '15 at 21:18
  • @StriplingWarrior I mean, I know one of them is null. I even kind of know which one. But did not understand why that results in the error, when I was trying to use the null-coalescing operator to account for it. The table that returns has one entry of a possible 3. In this case, I expected it not to return, but wanted to result with an empty string when that happens. – Dave Johnson Apr 27 '15 at 21:20
  • 1
    @DaveJohnson: Yeah, the problem is you were using the null-coalescing operator *after* the point where you tried accessing a property from a null value. Glad you got things figured out. – StriplingWarrior Apr 27 '15 at 21:42

4 Answers4

3

This is probably going to get closed because your question duplicates the 1000000000000 other NullReferenceException questions that have been asked before.

Think about this .Where(p => p.PhoneTypeID == 2).FirstOrDefault().Phone

What happens when there is no item in tblCustomerContactInformationPhone with a PhoneTypeID of 2? FirstOrDefault gives you 'default' which in this case is null and then you do TheValueRetuendFromFirstOrDefaultWhichIsNull.Phone and get a NullReferenceException.

Instead break it into two lines.

string phone = String.Empty;
var temp = cust.tblCustomerContactInformation1.tblCustomerContactInformationPhone.Where(p => p.PhoneTypeID == 2).FirstOrDefault();

if (temp != null)
    phone = temp.Phone;

EDIT: Another option is to use select to get the value of Phone so that you can use the null coalescing operator like you're trying to. That would look like this;

var phone = cust.tblCustomerContactInformation1.tblCustomerContactInformationPhone.Where(p => p.PhoneTypeID == 2).Select(x => x.Phone).FirstOrDefault() ?? String.Empty;

This works fine because the lambda expression in the select will be applied to 0 elements if none are returned by the where so you end up just getting null back from FirstOrDefault in which case you'll take the empty string.

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
  • Thanks. Both approaches work, though your updated version is basically what I was trying to do. Not understanding much about Linq makes these simple things difficult for me. – Dave Johnson Apr 27 '15 at 21:21
1

in this clause :

cust.tblCustomerContactInformation1.tblCustomerContactInformationPhone.Where(p => p.PhoneTypeID == 2).FirstOrDefault().Phone ?? String.Empty;

You are accessing to Phone property of a possible Null reference.

You can do as follows:

var contactinfo = cust.tblCustomerContactInformation1.tblCustomerContactInformationPhone.FirstOrDefault(p => p.PhoneTypeID == 2);

if(contactinfo != null){
    Console.Write(contactinfo.Phone);

}
DarthVader
  • 52,984
  • 76
  • 209
  • 300
1

Most likely there aren't any entries that match your PhoneTypeID == 2 criteria, so .FirstOrDefault() returns null. Attempting to access .Phone property off of that throws a null reference exception.

Other answers have indicated that you can do a null-check on the result of .FirstOrDefault(), but there's another trick you can use with Entity Framework to only query for the Phone property, and avoid selecting more data than you need:

altPhone = cust.tblCustomerContactInformation1.tblCustomerContactInformationPhone
    .Where(p => p.PhoneTypeID == 2)
    .Select(p => p.Phone)
    .FirstOrDefault() ?? "";

This works because SQL Server doesn't throw exceptions when it runs into null values, but propagates the null values instead.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
0

When you use FirstOrDefault, the "Default" value of the tblCustomerContactInformationPhone is null. If the query for that table doesn't find anything (meaning there's no record which meets the PhoneTypeID of 2) you'll get null and in your code you're trying to get the Phone of the null. Your ?? is useless here.

Alireza Noori
  • 14,961
  • 30
  • 95
  • 179