kriss
kriss

Reputation: 1015

Linq query - get first object of related entity

I have a problem with my query

var ninjas = from n in this.dbContext.Ninjas
                        join e in this.dbContext.Equipment on n.Id equals e.NinjaId
                        select ( new NinjaModel()
                        {
                            Id = n.Id,
                            Name = n.Name,
                            FirstEquipmentItemName = n.Equipment.FirstOrDefault()?.Name,
                            BornDate = DbFunctions.TruncateTime(n.BornDate).Value
                        });

I cant use FirstOrDefault in my query and I want to get first item name of ninja equipment there. Is it possible? I know I can use

 this.dbContext.Ninjas.AsEnumerable()

but then DbFunctions.TruncateTime wont work.

Upvotes: 0

Views: 632

Answers (2)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236188

Your problems is usage of null-conditional operator in query:

FirstEquipmentItemName = n.Equipment.FirstOrDefault()?.Name

That will give an error

An expression tree lambda may not contain a null propagating operator.

What you need - just get name without null-conditional operator. In case if there is no related entites, name will have null value:

FirstEquipmentItemName = n.Equipment.FirstOrDefault().Name

What is happening behind the scene - EF generates SQL query which returns TOP (1) equipment name from related table. Something like:

   SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[Name] AS [Name],
    (SELECT TOP (1)
        [Extent2].[Name] AS [Name]
        FROM [dbo].[Equipment] AS [Extent2]
        WHERE [Extent1].[Id] = [Extent2].[Id]) AS [C1]
    FROM [dbo].[Ninjas] AS [Extent1]

Upvotes: 2

Nathangrad
Nathangrad

Reputation: 1466

You can use .ElementAt(0) which will return the first element from the query.
You can validate that there is actually an element at position 0 by using if (ninjas.Count() > 0)

Upvotes: 1

Related Questions