【发布时间】:2017-05-05 19:18:20
【问题描述】:
我正在运行这样的代码:
var somethings = db.Somethings.Select(s => new SomethingViewModel
{
Id = s.Id,
Name = s.Name,
IsActive = s.IsActive
SubSomethings = s.SubSomethings.Select(ss => new SubSomethingViewModel
{
Id = ss.Id,
Name = ss.Name,
IsActive = ss.IsActive
}).Where(wss => wss.IsActive)
}).Where(ws => ws.IsActive && (ws.SubSomethings.Any())) //remove elements if no SubSomethings
.ToList();
如您所见,这是一对多的关系。 Something 中有一个 SubSomethings 的列表。如果我取出 && (ws.SubSomethings.Any()),我会得到一个非常快的列表返回。
但是,我只想在列表中包含至少有一个 SubSomething 的Somethings。我还尝试了以下方法并获得了同样可怕的效率:
var somethings = db.Somethings.Select(s => new SomethingViewModel
{
Id = s.Id,
Name = s.Name,
IsActive = s.IsActive
SubSomethings = s.SubSomethings.Select(ss => new SubSomethingViewModel
{
Id = ss.Id,
Name = ss.Name,
IsActive = ss.IsActive
}).Where(wss => wss.IsActive)
}).Where(ws => ws.IsActive)
.ToList(); //this finishes very quickly
var somethings2 = somethings.Where(s => s.SubSomethings.Any()).ToList(); //This is where the code bogged down
如何重新编写查询以使陷入困境的代码更快?需要注意的一件事:这适用于一两条记录。当我达到超过 8000 条记录时,至少需要四分钟。
这是我在 SubSomething 表上为SomethingId的外键创建的索引,对应Something.Id
CREATE NONCLUSTERED INDEX [IX_SubSomething_SomethingId] ON [dbo].[SubSomething]
(
[SomethingId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
这里是SubSomething.SomethingId的外键创建:
ALTER TABLE [dbo].[SubSomething] WITH CHECK ADD CONSTRAINT [FK_SubSomething_Something_SomethingId] FOREIGN KEY([SomethingId])
REFERENCES [dbo].[Something] ([Id])
GO
ALTER TABLE [dbo].[SubSomething] CHECK CONSTRAINT [FK_SubSomething_Something_SomethingId]
GO
【问题讨论】:
-
@Gusman - 因为 Count 需要消耗整个数据,所以速度会变慢
-
发送到服务器的查询是什么样的?在您的第一个版本上执行 .ToString() 而不是 .ToList() 来获取它。如果您在 SSMS 中运行它,查询计划又会是什么样子?
-
@GiladGreen 不,它将转换为 SQL Count,它将使用主键索引的长度。
-
您可能应该在两个查询中获取数据。
-
@Gusman 它不能转换为 SQL,至少不能转换为 OP 的第二种形式。
.Any()在一个仅使用Enumerable方法的表达式中,没有任何东西可供Queryable操作。
标签: c# .net entity-framework linq entity-framework-core