I get the following error that I'm having trouble solving:
CS1929
'List<ExternalLink>' does not contain a definition for 'Select' and 
the best extension method overload 
'Queryable.Select<ExternalLink, ExternalLinkDto>(IQueryable<ExternalLink>,
    Expression<Func<ExternalLink, ExternalLinkDto>>)' 
requires a receiver of type
'System.Linq.IQueryable<MyProject.Models.Entities.ExternalLink>'
What I'm trying to achieve is this example from @JonSkeet
https://stackoverflow.com/a/34649951/3850405
The reason for doing this is exactly as the original post, avoid duplicate code for LINQ Select and still only project the properties I need for querying efficiently via EF Core.
public static IQueryable<ProductSummaryDtoHelper> QueryProductSummary(this IQueryable<Product> query)
{
    var summary = query.Select(product => new ProductSummaryDtoHelper()
    {
        UnresolvedThreatAndCountermeasures =
            product.ThreatAndCountermeasures.Where(tac => !tac.NotApplicable && !(tac.Verified && tac.Implemented)).Select(
                vuln => new ProductSummaryVulnerabilityDtoHelper()
                {
                    ExternalLinksHelper = vuln.ExternalLinks.Select(ExternalLinkDto.Conversion),
                    ExternalLinksHelperThreat = vuln.Threat.ExternalLinks.Select(externalLink => new ExternalLinkDto()
                    {
                        Id = externalLink.Id,
                        Link = externalLink.Link,
                        LinkType = externalLink.LinkType,
                        LinkText = externalLink.LinkText
                    }),
                    ExternalLinksHelperThreatFork = vuln.Threat.Fork.ExternalLinks.Select(externalLink => new ExternalLinkDto()
                    {
                        Id = externalLink.Id,
                        Link = externalLink.Link,
                        LinkType = externalLink.LinkType,
                        LinkText = externalLink.LinkText
                    })
                })
    });
    return summary;
}
ExternalLinkDto class:
public class ExternalLinkDto : EntityDto
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    ...
    public static Expression<Func<ExternalLink, ExternalLinkDto>> Conversion = externalLink =>
            new ExternalLinkDto()
            {
                Id = externalLink.Id,
                Link = externalLink.Link,
                LinkType = externalLink.LinkType,
                LinkText = externalLink.LinkText
            };
}
The following code works but I do not like the code duplication:
public static IQueryable<ProductSummaryDtoHelper> QueryProductSummary(this IQueryable<Product> query)
{
    var summary = query.Select(product => new ProductSummaryDtoHelper()
    {
        UnresolvedThreatAndCountermeasures =
            product.ThreatAndCountermeasures.Where(tac => !tac.NotApplicable && !(tac.Verified && tac.Implemented)).Select(
                vuln => new ProductSummaryVulnerabilityDtoHelper()
                {
                    ExternalLinksHelper = vuln.ExternalLinks.Select(externalLink => new ExternalLinkDto()
                    {
                        Id = externalLink.Id,
                        Link = externalLink.Link,
                        LinkType = externalLink.LinkType,
                        LinkText = externalLink.LinkText
                    }),
                    ExternalLinksHelperThreat = vuln.Threat.ExternalLinks.Select(externalLink => new ExternalLinkDto()
                    {
                        Id = externalLink.Id,
                        Link = externalLink.Link,
                        LinkType = externalLink.LinkType,
                        LinkText = externalLink.LinkText
                    }),
                    ExternalLinksHelperThreatFork = vuln.Threat.Fork.ExternalLinks.Select(externalLink => new ExternalLinkDto()
                    {
                        Id = externalLink.Id,
                        Link = externalLink.Link,
                        LinkType = externalLink.LinkType,
                        LinkText = externalLink.LinkText
                    })
                })
    });
    return summary;
}
This results in the following SQL sent:
SELECT [t0].[Id], [t1].[Id] AS [Id0], [t3].[Id] AS [Id1], [e].[Id] AS [Id2], [e].[Link], [e].[LinkType], [e].[LinkText], [e0].[Id] AS [Id3], [e0].[Link] AS [Link0], [e0].[LinkType] AS [LinkType0], [e0].[LinkText] AS [LinkText0], [e1].[Id] AS [Id4], [e1].[Link] AS [Link1], [e1].[LinkType] AS [LinkType1], [e1].[LinkText] AS [LinkText1], [t0].[ProductId]
  FROM [ThreatAndCountermeasure] AS [t0]
  INNER JOIN [Threats] AS [t1] ON [t0].[ThreatId] = [t1].[Id]
  LEFT JOIN [Threats] AS [t3] ON [t1].[ForkId] = [t3].[Id]
  LEFT JOIN [ExternalLink] AS [e] ON [t0].[Id] = [e].[ThreatAndCountermeasureId]
  LEFT JOIN [ExternalLink] AS [e0] ON [t1].[Id] = [e0].[ThreatId]
  LEFT JOIN [ExternalLink] AS [e1] ON [t3].[Id] = [e1].[ThreatId]
  WHERE [t0].[NotApplicable] = CAST(0 AS bit) AND ([t0].[Verified] = CAST(0 AS bit) OR [t0].[Implemented] = CAST(0 AS bit))
Creating an extension method like this also works:
public static IQueryable<ProductSummaryDtoHelper> QueryProductSummary(this IQueryable<Product> query)
{
    var summary = query.Select(product => new ProductSummaryDtoHelper()
    {
        UnresolvedThreatAndCountermeasures =
            product.ThreatAndCountermeasures.Where(tac => !tac.NotApplicable && !(tac.Verified && tac.Implemented)).Select(
                vuln => new ProductSummaryVulnerabilityDtoHelper()
                {
                    ExternalLinksHelper = vuln.ExternalLinks.MapToExternalLinkDto(),
                    ExternalLinksHelperThreat = vuln.Threat.ExternalLinks.MapToExternalLinkDto(),
                    ExternalLinksHelperThreatFork = vuln.Threat.Fork.ExternalLinks.MapToExternalLinkDto()
                })
    });
    return summary;
}
public static IEnumerable<ExternalLinkDto> MapToExternalLinkDto(this List<ExternalLink> externalLinks)
{
    var summary = externalLinks.Select(externalLink => new ExternalLinkDto()
    {
        Id = externalLink.Id,
        Link = externalLink.Link,
        LinkType = externalLink.LinkType,
        LinkText = externalLink.LinkText
    });
    return summary;
}
However the SQL generated will pick up every extra field and I do not want that:
SELECT [t0].[Id], [t1].[Id] AS [Id0], [t3].[Id] AS [Id1], [e].[Id] AS [Id2], [e].[Created], [e].[CreatedById], [e].[Guid], [e].[Link], [e].[LinkText], [e].[LinkType], [e].[PeriodEnd], [e].[PeriodStart], [e].[ProductId], [e].[ThreatAndCountermeasureId], [e].[ThreatId], [e].[Updated], [e].[UpdatedById], [e].[Version], [e0].[Id] AS [Id3], [e0].[Created] AS [Created0], [e0].[CreatedById] AS [CreatedById0], [e0].[Guid] AS [Guid0], [e0].[Link] AS [Link0], [e0].[LinkText] AS [LinkText0], [e0].[LinkType] AS [LinkType0], [e0].[PeriodEnd] AS [PeriodEnd0], [e0].[PeriodStart] AS [PeriodStart0], [e0].[ProductId] AS [ProductId0], [e0].[ThreatAndCountermeasureId] AS [ThreatAndCountermeasureId0], [e0].[ThreatId] AS [ThreatId0], [e0].[Updated] AS [Updated0], [e0].[UpdatedById] AS [UpdatedById0], [e0].[Version] AS [Version0], [e1].[Id] AS [Id4], [e1].[Created] AS [Created1], [e1].[CreatedById] AS [CreatedById1], [e1].[Guid] AS [Guid1], [e1].[Link] AS [Link1], [e1].[LinkText] AS [LinkText1], [e1].[LinkType] AS [LinkType1], [e1].[PeriodEnd] AS [PeriodEnd1], [e1].[PeriodStart] AS [PeriodStart1], [e1].[ProductId] AS [ProductId1], [e1].[ThreatAndCountermeasureId] AS [ThreatAndCountermeasureId1], [e1].[ThreatId] AS [ThreatId1], [e1].[Updated] AS [Updated1], [e1].[UpdatedById] AS [UpdatedById1], [e1].[Version] AS [Version1], [t0].[ProductId] AS [ProductId2]
FROM [ThreatAndCountermeasure] AS [t0]
INNER JOIN [Threats] AS [t1] ON [t0].[ThreatId] = [t1].[Id]
LEFT JOIN [Threats] AS [t3] ON [t1].[ForkId] = [t3].[Id]
LEFT JOIN [ExternalLink] AS [e] ON [t0].[Id] = [e].[ThreatAndCountermeasureId]
LEFT JOIN [ExternalLink] AS [e0] ON [t1].[Id] = [e0].[ThreatId]
LEFT JOIN [ExternalLink] AS [e1] ON [t3].[Id] = [e1].[ThreatId]
WHERE [t0].[NotApplicable] = CAST(0 AS bit) AND ([t0].[Verified] = CAST(0 AS bit) OR [t0].[Implemented] = CAST(0 AS bit)