我首先使用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使用计数中的特定列而不是所有列?
答案 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() };