gpt4 book ai didi

c# - 了解 LINQ 如何编译为 ADO.NET SQL 语句

转载 作者:行者123 更新时间:2023-11-30 23:07:56 25 4
gpt4 key购买 nike

我有一个看似非常简单的 LINQ 语句,但它生成的 SQL 对我来说没有意义,而且执行时间比我预期的要长得多。我只是想了解 LINQ 在做什么,这样我就可以弄清楚为什么它运行得这么慢。一个类似的 SQL 语句用时不到一秒,但 LINQ 大约需要 20 秒。

代码如下:

// This line takes 20 seconds to return.
var alertEvents = GetFilteredAlertEvents(alert.AlertEvents, db).ToList<AlertEvent>();

private static IEnumerable<AlertEvent> GetFilteredAlertEvents(ICollection<AlertEvent> alertEvents, SlalomEREntities db)
{
Guid marketAlertReceiverGroupId = new Guid(ConfigurationManager.AppSettings["MarketAlertReceiverGroupId"]);
var subQuery = from ae in alertEvents
join tr in db.TargetResources on ae.ResourceId equals tr.ResourceID
join atr in db.AlertTargetResources on tr.ResourceID equals atr.TargetResourceID
where atr.AlertTargetID == marketAlertReceiverGroupId
select ae.AlertEventId;

return from alertEvent in alertEvents
where !subQuery.Contains(alertEvent.AlertEventId)
select alertEvent;
}

在 SSMS 中,子选择返回 3126 行没有 where,只有 127 行有它。 SSMS 中的主 select 返回没有子选择的 365 行。带子选择的完整选择返回 238 行。数据不多。

使用 Visual Studio 的诊断工具,我看到了从 LINQ 生成的 14 个 SQL 语句。它们中的每一个都是一个简单的 SQL 选择,我没有看到任何连接,也没有看到 where 比较。这是我在“诊断工具事件”窗口中看到的示例 SQL 语句:

SELECT 
[Extent1].[AlertTargetID] AS [AlertTargetID],
[Extent1].[TargetResourceID] AS [TargetResourceID],
[Extent1].[CreatedAt] AS [CreatedAt],
[Extent1].[CreatedBy] AS [CreatedBy]
FROM [dbo].[AlertTargetResource] AS [Extent1]

还有13条类似的SQL语句。

这是我要复制的 SQL。

select *
from AlertEvent ae1
where ae1.AlertEventId not in
(select ae.AlertEventId
from AlertEvent ae
join TargetResource tr on ae.ResourceId = tr.ResourceID
join AlertTargetResource atr on atr.TargetResourceID = tr.ResourceID
where atr.AlertTargetID = '89bd4ea5-5d56-4b8a-81ba-5a9e5991ba64')

这是我的问题:

  1. 为什么 LINQ 会生成 14 个简单的选择而不是带有连接和位置的单个选择?
  2. 我怎样才能加快我认为是一段简单的代码的速度?

最佳答案

在方法的第一部分,subQuery 是尚未针对数据库运行的查询。在第二部分(围绕您的 return 语句),您将多次调用该查询。

Entity Framework 如何处理这种情况并不总是很明显,但在这里它似乎为 alertEvents 中的每个项目调用查询。

您真正需要的是查询返回的 ID 列表,然后将该列表用于该方法的第二部分。要将查询转换为该查询返回的数据,您可以使用 ToList()。此扩展方法将执行查询并返回数据结果。

在下面的代码中,subQuery 现在是 ID 的集合。

private static IEnumerable<AlertEvent> GetFilteredAlertEvents(ICollection<AlertEvent> alertEvents, SlalomEREntities db)
{
Guid marketAlertReceiverGroupId = new Guid(ConfigurationManager.AppSettings["MarketAlertReceiverGroupId"]);
var subQuery = (from ae in alertEvents
join tr in db.TargetResources on ae.ResourceId equals tr.ResourceID
join atr in db.AlertTargetResources on tr.ResourceID equals atr.TargetResourceID
where atr.AlertTargetID == marketAlertReceiverGroupId
select ae.AlertEventId).ToList();

return from alertEvent in alertEvents
where !subQuery.Contains(alertEvent.AlertEventId)
select alertEvent;
}

关于c# - 了解 LINQ 如何编译为 ADO.NET SQL 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46855419/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com