SWa
SWa

Reputation: 4363

Linq return null for no results

In the following simplified example, I want to set Containers to null should there be no no matches.

_viewModel.Materials = _jobMaterials.Select(x=> new {

    //Containers that the material my be in
    Containers = (materialContainers.Where(mcl => mcl.Field<string>("MATKey") == x.Field<string>("MATKey")).Any()) ?
                    materialContainers.Where(mcl => mcl.Field<string>("MATKey") == x.Field<string>("MATKey")).Select(mcl => new
                    {
                        Id = mcl.Field<int>("SERIDNumber"),
                        Description = mcl.Field<string>("SERDescription").Trim(),
                        Volume = mcl.Field<int>("SERVolume"),
                        ContractedStatus = mcl.Field<int>("Contracted"),
                        OnJob = Convert.ToBoolean(mcl.Field<int>("OnJob"))
                    }) : null

});

The above works, but is there a more succinct method? Like a combination of DefaultIfEmpty and FirstOrDefault.

Neither works in isolation, FirstOrDefault returns a single item when there are multiple matches whereas DefaultIfEmpty returns a collection containing null if there are no matches.

Upvotes: 0

Views: 211

Answers (3)

SWa
SWa

Reputation: 4363

Added a helper method

public static IEnumerable<object> NullIfEmpty(this IEnumerable<object> item)
{
        return item.Any() ? item : null;
}

Usage:

_viewModel.Materials = _jobMaterials.Select( material => new {

    //Containers that the material my be in
    Containers = materialContainers.Where(mcl => mcl.Field<string>("MATKey") == material.Field<string>("MATKey"))
                .Select( mcl => new {
                            Id = mcl.Field<int>("SERIDNumber"),
                            Description = mcl.Field<string>("SERDescription").Trim(),
                            Volume = mcl.Field<int>("SERVolume"),
                            ContractedStatus = mcl.Field<int>("Contracted"),
                            OnJob = Convert.ToBoolean(mcl.Field<int>("OnJob"))
                        })
                .NullIfEmpty()

});

Upvotes: 0

user3438528
user3438528

Reputation: 15

use DefaultIfEmpty Function first then Select example: data.collection.Where(i => i.Type == type) .DefaultIfEmpty(defaultObject) .Select(i => i.Count);

Upvotes: 0

ASh
ASh

Reputation: 35720

try this code:

_viewModel.Materials = _jobMaterials
.Select(x=>materialContainers.Where(mcl => mcl.Field<string>("MATKey") == x.Field<string>("MATKey")))
.Select(m => new {
      //Containers that the material my be in
       Containers = m.Any() ?
                    m.Select(mcl => new
                    {
                        Id = mcl.Field<int>("SERIDNumber"),
                        Description = mcl.Field<string>("SERDescription").Trim(),
                        Volume = mcl.Field<int>("SERVolume"),
                        ContractedStatus = mcl.Field<int>("Contracted"),
                        OnJob = Convert.ToBoolean(mcl.Field<int>("OnJob"))
                    }) : null

Upvotes: 1

Related Questions