Linq对象引用不是对象的实例

时间:2014-03-07 19:47:55

标签: c# asp.net asp.net-mvc linq nullreferenceexception

运行Linq查询时遇到问题我收到错误Object reference not set to an instance of an object.

var RestaurantName = (from r in objCtx.Restaurants
                      where r.id == item.restaurantid
                      select r).SingleOrDefault<Restaurant>().Name;

然后我将查询更改为

var RestaurantName = (from r in objCtx.Restaurants
                      where r.id == item.restaurantid
                      select r).Single<Restaurant>().Name;

但我收到错误Sequence contains no elements。我检查了变量,它正在返回一个餐馆名称。但我不明白为什么我会收到这些错误。

5 个答案:

答案 0 :(得分:4)

问题是你的linq查询返回一个空集合:

from r in objCtx.Restaurants
where r.id == item.restaurantid
select r

在第一个示例中调用SingleOrDefault时,它会返回null(即默认值)。您收到object reference not set ...,因为您尝试在空引用上调用Name属性。

在第二个示例中,您拨打Single。当您在包含0或+1元素的列表上执行此操作时,将引发异常。 (正如您所经历的那样)。

解决方案是确保始终检索单个实例,或在访问该对象的任何属性之前进行检查

答案 1 :(得分:2)

正如其他人所说,你的结果集是空的。这将导致Single失败(这是记录的),并且它将导致SingleOrDefault返回给定类型的默认值(在类的情况下为null)。

除了其他答案(使用空值守卫)中提供的解决方案之外,还有另一个使用更多LINQ:

var RestaurantName = (from r in objCtx.Restaurants
                      where r.id == item.restaurantid
                      select r).DefaultIfEmpty(new Restaurant() { Name="None" })
                               .SingleOrDefault().Name;

DefaultIfEmpty会将SingleOrDefault返回的“默认”值从null更改为提供的值。这样您就可以安全地访问Name属性。根据您的Restaurant类的确切构建方式,您可能希望以不同方式创建默认值。你应该能够提供类似new { Name = "None" }的默认值,创建一个匿名对象,但这取决于你。

答案 2 :(得分:0)

问题是集合中没有满足条件的项目。 SingleOrDefault返回null(对于引用类型),因此在第一个版本中,您会收到NullReferenceException。如果没有返回的元素,Single会抛出异常,这就是第二种方法失败的原因。

您需要检查是否有任何结果:

var restaurant = (from r in objCtx.Restaurants
                  where r.id == item.restaurantid
                  select r).SingleOrDefault<Restaurant>();
string restaurantName;
if (restaurant != null)
    restaurantName = restaurant.Name;
else
    restaurantName = string.Empty;

答案 3 :(得分:0)

如果如你所说,你的第二个代码示例(使用Single的那个)没有返回任何元素,那么第一个(使用SingleOrDefault的代码)返回null。并且您无法从.Name获取null属性。

我认为您需要验证您的查询。直接查看数据,或者甚至只是遍历数据并查看输出结果:

var restaurants = from r in objCtx.Restaurants
                  where r.id == item.restaurantid
                  select r;

foreach (var restaurant in restaurants)
{
    string name = restaurant.Name;
}

我猜测循环永远不会执行,因为它是空的,你需要弄清楚你的查询有什么问题。

如果您需要处理可能不返回任何元素的场景,那么您只需要进行if检查:

var restaurant = (from r in objCtx.Restaurants
                  where r.id == item.restaurantid
                  select r).SingleOrDefault<Restaurant>();

string restaurantName;
if (restaurant == null)
    restaurantName = string.Empty;
else
    restaurantName = restaurant.Name;

答案 4 :(得分:0)

如果序列中没有项目,则单个将通过异常。

尝试:

var RestaurantName = ((from r in objCtx.Restaurants
                          where r.id == item.restaurantid
                          select r).Any()) ? (from r in objCtx.Restaurants
                          where r.id == item.restaurantid
                          select r).SingleOrDefault<Restaurant>().Name : string.empty;