Conditional filling element of anonymous type in linq request

I am having a problem with the following LINQ query. When the subquery (item.Items) has no objects, I get the exception "Value cannot be empty. Parameter name: source.".

How can I make an internal query return an empty list of elements in 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 question:

 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 or avoid the null item.Items value? I have a feeling that I'm just not enough.

+4
source share
1 answer

Assuming LINQ to Objects and the class name of the same Item , go to the following:

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

?? called the operator with zero coalescence 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 that you cannot apply queries to a null object, and it seems that item.Items may be null in your case. A better solution would be to ensure that the Items property returns a null sequence when empty, not null .

If you do not have control over the StreamItem class, but in many cases you have to perform such requests, it can pay off to create a β€œsafe” extension method that will return β€œdenied” elements:

 public static IEnumerable<Item> SafeGetSubItems(this StreamItem parent) { return parent.Items ?? Enumerable.Empty<Item>(); } 

This will allow you to always write:

 Items = from subItem in item.SafeGetSubItems() select new { // ... } 
+6
source

All Articles