在linq中指定具有左外连接的计数列

时间:2015-04-07 00:21:32

标签: c# sql linq linq-to-entities left-join

我首先使用EF代码和迁移。我有两个实体:

public class LicensedSoftware
{
    public int Id { get; set; }
    public int ResourceId { get; set; }
    public int SoftwareDetailId { get; set; }
}

public class SoftwareDetail
{
    public int Id { get; set; }
    public string FamilyName { get; set; }
    public string SoftwareName { get; set; }
    public string Version { get; set; }
}

我正在尝试指定在执行左外连接时要依赖的列,但它似乎只使用Count(*)

这是我的linq:

SoftwareDetails
.GroupJoin(LicensedSoftwares, l => l.Id, c => c.SoftwareDetailId, 
    (l, c) => 
        new { Licensed = l, Details = c.DefaultIfEmpty() })
.SelectMany(x => x.Details, (x, merged) => new { Details = merged, x.Licensed })
.GroupBy(x => x.Licensed, x => x.Details, 
    (key, g) => 
        new { Licensed = key, Count = g.Count() })

生成的SQL是:

SELECT COUNT(*) AS [Count]
, [t0].[Id], [t0].[FamilyName], [t0].[SoftwareName], [t0].[Version]
FROM [SoftwareDetails] AS [t0]
LEFT OUTER JOIN [LicensedSoftwares] AS [t1] ON [t0].[Id] = [t1].[SoftwareDetailId]
GROUP BY [t0].[Id], [t0].[FamilyName], [t0].[SoftwareName], [t0].[Version]

这也会计算SoftwareDetails表中的行,所以我的计数总是至少为1.

我希望它(注意选择中的计数):

SELECT COUNT([t1].[Id]) AS [Count]
, [t0].[Id], [t0].[FamilyName], [t0].[SoftwareName], [t0].[Version]
FROM [SoftwareDetails] AS [t0]
LEFT OUTER JOIN [LicensedSoftwares] AS [t1] ON [t0].[Id] = [t1].[SoftwareDetailId]
GROUP BY [t0].[Id], [t0].[FamilyName], [t0].[SoftwareName], [t0].[Version]

最接近我得到的正确结果是:

SoftwareDetails
    .Select (sd => new 
    { 
        sd.Id, sd.FamilyName, sd.SoftwareName, sd.Version, 
        Count = LicensedSoftwares
                    .Where(ls => ls.SoftwareDetailId == sd.Id && ls.Id != null)
                    .Count()
    })

但我不喜欢它生成的SQL:

SELECT [t0].[Id], [t0].[FamilyName], [t0].[SoftwareName], [t0].[Version], (
    SELECT COUNT(*)
    FROM [LicensedSoftwares] AS [t1]
    WHERE [t1].[SoftwareDetailId] = [t0].[Id]
) AS [Count]
FROM [SoftwareDetails] AS [t0]

有没有人知道让EF使用计数中的特定列而不是所有列?

1 个答案:

答案 0 :(得分:0)

关闭主题问题:不应该将SoftwareDetail作为孩子而且LicencedSoftware是父母,所以forieng密钥要反过来吗?

与我的问题无关,请尝试以下内容:

 var query = from softwareDetail in context.SoftwareDetails
                        join licensedSoftware in context.LicensedSoftwares
                            on softwareDetail.Id equals licensedSoftware.SoftwareDetailId
                        select new { softwareDetail, licensedSoftware }
                            into temp
                            group temp by temp.softwareDetail into temp2
                            select new { temp2, count = temp2.Count() };