我有一个具有Group By子句的linq查询,但是Group By不在SQL Server上发生。 我尝试了一个简单的查询,并且在SQL Server上发生了分组依据。 请指导我为什么这种不同的行为?? 我希望在服务器上进行分组以提高性能。
如果我登录sql查询,我将获得分组依据的简单查询:
var testt = (from doc in _patientRepository.Documents
group doc by doc.DocumentType into G
select new
{
Key = G.Key
}).ToList();
生成的sql:
Executed DbCommand (247ms) [Parameters=[], CommandType='Text',
CommandTimeout='30']
SELECT [doc].[DocumentType] AS [Key]
FROM [Document] AS [doc]
GROUP BY [doc].[DocumentType]
问题查询:
var patX = (from doc in _patientRepository.Documents
join pat in _patientRepository.Patients
on doc.PatientId.ToString().ToLower() equals pat.PatientId.ToString().ToLower()
where doc.Source.ToLower() != "testclient.server.postman" &&
pat.Deleted == false && sfHCPs.Contains(pat.HcpId.ToLower())
select new Document()
{
DocumentId = doc.DocumentId,
CreationDateTime = doc.CreationDateTime,
DocumentType = doc.DocumentType,
PatientId = doc.PatientId,
DocumentTypeVersion = doc.DocumentTypeVersion,
Source = doc.Source,
PayloadLeft = DocumentMapper.DeserializePayload(doc.PayloadLeft),
PayloadRight = DocumentMapper.DeserializePayload(doc.PayloadRight),
PayloadBoth = DocumentMapper.DeserializePayload(doc.PayloadBoth),
IsSalesforceSynced = doc.IsSalesforceSynced,
HcpId = pat.HcpId
}).GroupBy(p => new { p.PatientId, p.DocumentType })
.Select(g => g.OrderByDescending(p => p.CreationDateTime).FirstOrDefault())
.Where(x => x.IsSalesforceSynced == false)
.ToList();
为什么没有生成group-by sql:
Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (200ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [doc].[DocumentId], [doc].[CreationDateTime], [doc].[DocumentType], [doc].[PatientId], [doc].[DocumentTypeVersion], [doc].[Source], [doc].[PayloadLeft], [doc].[PayloadRight], [doc].[PayloadBoth], [doc].[IsSalesforceSynced], [pat].[HcpId]
FROM [Document] AS [doc]
INNER JOIN [Patient] AS [pat] ON LOWER(CONVERT(VARCHAR(36), [doc].[PatientId])) = LOWER(CONVERT(VARCHAR(36), [pat].[PatientId]))
WHERE ((LOWER([doc].[Source]) <> N'testclient.server.postman') AND ([pat].[Deleted] = 0)) AND LOWER([pat].[HcpId]) IN (N'4e7103a9-7dff-4fa5-b540-a32a31be2997', N'abc1', N'def2', N'ghi3')
ORDER BY [doc].[PatientId], [doc].[DocumentType]
我尝试了以下方法,但是生成了相同的sql:
var patX = ((from doc in _patientRepository.Documents
join pat in _patientRepository.Patients
on doc.PatientId.ToString().ToLower()
equals pat.PatientId.ToString().ToLower()
where doc.Source.ToLower() != "testclient.server.postman" &&
pat.Deleted == false && sfHCPs.Contains(pat.HcpId.ToLower())
select new Document()
{
DocumentId = doc.DocumentId,
CreationDateTime = doc.CreationDateTime,
DocumentType = doc.DocumentType,
PatientId = doc.PatientId,
DocumentTypeVersion = doc.DocumentTypeVersion,
Source = doc.Source,
PayloadLeft = DocumentMapper.DeserializePayload(doc.PayloadLeft),
PayloadRight = DocumentMapper.DeserializePayload(doc.PayloadRight),
PayloadBoth = DocumentMapper.DeserializePayload(doc.PayloadBoth),
IsSalesforceSynced = doc.IsSalesforceSynced,
HcpId = pat.HcpId
}).GroupBy(p => new { p.PatientId, p.DocumentType })
.Select(g => g.OrderByDescending(p => p.CreationDateTime).FirstOrDefault())
.Where(x => x.IsSalesforceSynced == false))
.ToList();
答案 0 :(得分:0)
在2.1版之前,在EF Core中,GroupBy LINQ运算符将始终在内存中进行评估。现在,在大多数情况下,现在支持将其转换为SQL GROUP BY子句。
更改代码:尝试将.GroupBy放在.select方法之前(首先选择)
答案 1 :(得分:0)
考虑对查询重新排序,以使新类的select
排在最后:
var p1 = from doc in _patientRepository.Documents
join pat in _patientRepository.Patients on doc.PatientId.ToString().ToLower() equals pat.PatientId.ToString().ToLower()
where doc.Source.ToLower() != "testclient.server.postman" && pat.Deleted == false && sfHCPs.Contains(pat.HcpId.ToLower())
group new { doc, pat.HcpId } by new { doc.PatientId, doc.DocumentType } into dpg
select dpg.OrderByDescending(dp => dp.doc.CreationDateTime).FirstOrDefault();
var patX = (from dp in p1
where !dp.doc.IsSalesforceSynced
select new Document() {
DocumentId = dp.doc.DocumentId,
CreationDateTime = dp.doc.CreationDateTime,
DocumentType = dp.doc.DocumentType,
PatientId = dp.doc.PatientId,
DocumentTypeVersion = dp.doc.DocumentTypeVersion,
Source = dp.doc.Source,
PayloadLeft = DocumentMapper.DeserializePayload(dp.doc.PayloadLeft),
PayloadRight = DocumentMapper.DeserializePayload(dp.doc.PayloadRight),
PayloadBoth = DocumentMapper.DeserializePayload(dp.doc.PayloadBoth),
IsSalesforceSynced = dp.doc.IsSalesforceSynced,
HcpId = dp.HcpId
})
.ToList();