Select only a single column in LINQ

89,047

Solution 1

//var Country = Countries.FirstOrDefault(o => o.Id == 100000581);
var personnelIds = context.Personnels
    .Where(p => p.Country.Id == 100000581)
    .Select(p => p.Id)
    .ToArray();

personnelIds.Dump();

Try this, it should be better.

Solution 2

Personnels collection will be populated via lazy loading when accessed, hence retrieving all of the fields from the DB. Here's what's happening...

// retrieves data and builds the single Country entity (if not null result)
var Country = Countries.FirstOrDefault(o => o.Id == 100000581);

// Country.Personnels accessor will lazy load and construct all Personnel entity objects related to this country entity object
// hence loading all of the fields
var personnelIds = Country.Personnels.Select(p => p.Id).ToArray();

You want something more like this:

// build base query projecting desired data
var personnelIdsQuery = dbContext.Countries
    .Where( c => c.Id == 100000581 )
    .Select( c => new
        {
            CountryId = c.Id,
            PersonnelIds = c.Personnels.Select( p => p.Id )
        }

// now do enumeration
// your example shows FirstOrDefault without OrderBy
// either use SingleOrDefault or specify an OrderBy prior to using FirstOrDefaul

var result = personnelIdsQuery.OrderBy( item => item.CountryId ).FirstOrDefault();

OR:

var result = personnelIdsQuery.SingleOrDefault();

Then get the array of IDs if not null

if( null != result )
{
    var personnelIds = result.PersonnelIds;
}

Solution 3

Try can also try grouping personnel into a single query

var groups =
    (from p in Personnel
     group p by p.CountryId into g
     select new 
     {
         CountryId = g.Key
         PersonnelIds = p.Select(x => x.Id)
     });
var personnelIds = groups.FirstOrDefault(g => g.Key == 100000581);
Share:
89,047
Stef Heyenrath
Author by

Stef Heyenrath

Updated on March 29, 2020

Comments

  • Stef Heyenrath
    Stef Heyenrath about 4 years

    The EntityModel is defined as: Personnel has a link to a Country

    When executing this code in LinqPad, I see that the SQL which is generated is not optimized (all fields are returned) in the first query ? What am I missing here or doing wrong ?

    Query 1 LINQ

    var Country = Countries.FirstOrDefault(o => o.Id == 100000581);
    var personnelIds = Country.Personnels.Select(p => p.Id).ToArray();
    personnelIds.Dump();
    

    Query 1 SQL

    exec sp_executesql N'SELECT [t0].[Id], [t0].[Version], [t0].[Identifier], [t0].[Name], , [t0].[UpdatedBy] FROM [Personnel] AS [t0] WHERE [t0].[Country_Id] = @p0',N'@p0 bigint',@p0=100000581
    



    Query 2 LINQ

    var Country = Countries.FirstOrDefault(o => o.Id == 100000581);
    var personnelIds2 = Personnels.Where(p => p.Country == Country).Select(p => p.Id).ToArray();
    personnelIds2.Dump();
    

    Query 2 SQL

    exec sp_executesql N'SELECT [t0].[Id] FROM [Personnel] AS [t0] WHERE [t0].[Country_Id] = @p0',N'@p0 bigint',@p0=100000581
    


    The database used is SQL Express 2008. And LinqPad version is 4.43.06