开发者

conditionally populating anonymous type member in linq query

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.GetStr开发者_StackOverflow社区eamItems()
                        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.


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
        {
            // ...
        }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜