对象引用错误 - Linq

时间:2015-04-27 21:01:12

标签: c# linq entity-framework

我是Linq和Entity Framework的新手,并且在此查询中收到空引用异常:

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;
)

tblCustomerContactInformationPhone中有一行。 Where子句应该删除它,我应该得到一个空字符串。但是,我得到了:

Object reference not set to an instance of an object.

我做错了什么,如何正确执行此操作以便将空结果集正确转换为空字符串?

链接的问题没有帮助,因为这是Linq的使用特有的,这个问题没有涵盖。 @ evanmcdonnal的回答非常有帮助,并解决了我的问题。

4 个答案:

答案 0 :(得分:2)

这可能会被关闭,因为你的问题重复了之前被问过的1000000000000个其他NullReferenceException问题。

想想这个.Where(p => p.PhoneTypeID == 2).FirstOrDefault().Phone

如果tblCustomerContactInformationPhonePhoneTypeID的{​​{1}}项中没有项目,会发生什么? FirstOrDefault为您提供'default',在这种情况下为null,然后您执行TheValueRetuendFromFirstOrDefaultWhichIsNull.Phone并获得NullReferenceException。

而是将其分成两行。

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

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

编辑:另一种选择是使用select来获取Phone的值,以便您可以像尝试一样使用空合并运算符。这看起来像这样;

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

这样可以正常工作,因为select中的lambda表达式将应用于0个元素,如果where不返回任何元素,那么你最终只能从FirstOrDefault返回null,在这种情况下你将获取空字符串。

答案 1 :(得分:1)

在本条款中:

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

您正在访问可能为空的引用的Phone属性。

您可以执行以下操作:

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

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

}

答案 2 :(得分:1)

很可能没有任何条目符合您的PhoneTypeID == 2条件,因此.FirstOrDefault()会返回null。尝试访问.Phone属性会引发空引用异常。

其他答案表明您可以对.FirstOrDefault()的结果进行空值检查,但是您可以使用Entity Framework的另一个技巧来查询Phone属性,并避免选择比您需要的更多数据:

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

这是有效的,因为SQL Server在运行为空值时不会抛出异常,而是传播空值。

答案 3 :(得分:0)

当您使用FirstOrDefault时,tblCustomerContactInformationPhone的“默认”值为null。如果该表的查询没有找到任何内容(意味着没有符合2的PhoneTypeID的记录),您将获得null,并且在您的代码中,您试图获得{{1} } Phone。你的null在这里毫无用处。