Reputation: 5220
I'm having a problem with the following LINQ query. When the nested query (item.Items) has no objects I'm getting the exception "Value cannot be null. Parameter name: source.".
How can I get the inner query to return an empty list to items within the query?
var items = from item in _repository.GetStreamItems()
select new
{
Title = item.Title,
Description = item.Description,
MetaData = item.MetaData,
ItemType = item.ItemType,
Items = from subItem in item.Items
select new
{
Title = subItem.Title,
Description = subItem.Description,
MetaData = subItem.MetaData,
ItemType = subItem.ItemType
}
};
Here's the same query written using method calls instead of query syntax. Same issue:
var items = _repository.GetStreamItems()
.Select(x => new { Title = x.Title, Description = x.Description, MetaData = x.MetaData, ItemType = x.ItemType,
Items = x.Items.Select(x2 => new { Title = x2.Title, Description = x2.Description, MetaData = x2.MetaData, ItemType = x2.ItemType,
Items = x2.Items.Select(x3 => new { Title = x3.Title, Description = x3.Description, MetaData = x3.MetaData, ItemType = x3.ItemType }) }) });
Any ideas how to test for or avoid the null item.Items value? I have a feeling it's something simple I'm missing.
Upvotes: 4
Views: 1375
Reputation: 268323
Assuming it's LINQ to Objects and single item class name is Item
, go with this one:
var items = from item in _repository.GetStreamItems()
select new
{
Title = item.Title,
Description = item.Description,
MetaData = item.MetaData,
ItemType = item.ItemType,
Items = from subItem in (item.Items ?? Enumerable.Empty<Item>())
select new
{
Title = subItem.Title,
Description = subItem.Description,
MetaData = subItem.MetaData,
ItemType = subItem.ItemType
}
};
??
is called null-coalescing operator and returns the value on the right if the value on the left is null
.
In your specific example, we provide an empty sequence instead of null
so the code does not crash.
The problem is you can't apply queries to a null
object, and it seems like item.Items
can be null
in your case. A better solution would be to ensure that Items
property returns a zero sequence when empty, not null
.
If you have no control over the StreamItem
class but have to do similar queries in many places, it might pay off to create a “safe” extension method that would return “denullified” items:
public static IEnumerable<Item> SafeGetSubItems(this StreamItem parent)
{
return parent.Items ?? Enumerable.Empty<Item>();
}
This would allow you to always write:
Items = from subItem in item.SafeGetSubItems()
select new
{
// ...
}
Upvotes: 6