簡體   English   中英

使用FirstOrDefault()怪異的LINQ to SQL超時問題

[英]Weird LINQ to SQL Timeout Issue using FirstOrDefault()

我有以下代碼超時:

        using (var ts = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
        {
            ECWSDataContext dc = new ECWSDataContext();

            IQueryable<Ticket> results = dc.Tickets;
            Business.TicketStatistic statistic = results
                .Select(r => new
                {
                    GroupID = 1,
                    IsVoided = r.IsVoided ? 1 : 0,
                    IsWarning = r.TicketFilingTypeID == 5 ? 1 : 0,
                    TotalFelonies = r.TotalFelonies,
                    TotalMisdemeanors = r.TotalMisdemeanors,
                    TotalInfractions = r.TotalInfractions,
                    TotalOrdinances = r.TotalOrdinances,
                    TotalWarnings = r.TotalWarnings
                })
                .GroupBy(t => t.GroupID)
                .Select(g => new Business.TicketStatistic()
                {
                    TotalTickets = g.Count(),
                    TotalVoids = g.Sum(x => x.IsVoided),
                    TotalTicketWarnings = g.Sum(x => x.IsWarning),
                    TotalFelonies = g.Sum(x => x.TotalFelonies),
                    TotalMisdemeanors = g.Sum(x => x.TotalMisdemeanors),
                    TotalInfractions = g.Sum(x => x.TotalInfractions),
                    TotalOrdinances = g.Sum(x => x.TotalOrdinances),
                    TotalOffenseWarnings = g.Sum(x => x.TotalWarnings)
                }).FirstOrDefault();
        }

我使用SQL Server Profiler對SQL進行了概要分析,並獲取了已執行的SQL。 正如預期的那樣,它包含一個TOP1。當我在SQL Management Studio中運行確切的SQL時,它很快就會回來。 但是,它在代碼中繼續超時。 令人驚訝的是,將其更改為以下內容就可以了:

        using (var ts = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
        {
            ECWSDataContext dc = new ECWSDataContext();

            IQueryable<Ticket> results = dc.Tickets;

            var stats = results
                .Select(r => new
                {
                    GroupID = 1,
                    IsVoided = r.IsVoided ? 1 : 0,
                    IsWarning = r.TicketFilingTypeID == 5 ? 1 : 0,
                    TotalFelonies = r.TotalFelonies,
                    TotalMisdemeanors = r.TotalMisdemeanors,
                    TotalInfractions = r.TotalInfractions,
                    TotalOrdinances = r.TotalOrdinances,
                    TotalWarnings = r.TotalWarnings
                })
                .GroupBy(t => t.GroupID)
                .Select(g => new Business.TicketStatistic()
                {
                    TotalTickets = g.Count(),
                    TotalVoids = g.Sum(x => x.IsVoided),
                    TotalTicketWarnings = g.Sum(x => x.IsWarning),
                    TotalFelonies = g.Sum(x => x.TotalFelonies),
                    TotalMisdemeanors = g.Sum(x => x.TotalMisdemeanors),
                    TotalInfractions = g.Sum(x => x.TotalInfractions),
                    TotalOrdinances = g.Sum(x => x.TotalOrdinances),
                    TotalOffenseWarnings = g.Sum(x => x.TotalWarnings)
                }).ToArray();

            Business.TicketStatistic statistic = stats.FirstOrDefault();
        }

我知道現在在將FirstOrDefault()應用於當前內存中的集合之前,先枚舉結果。 但是,在第一種情況下直接在SQL Server中直接執行相同的SQL輸出沒有問題,這似乎很奇怪。

有人可以解釋這是怎么回事嗎? 在這種情況下,無論如何,它都是始終返回一行的組查詢。 因此,我很幸運能夠在應用FirstOrDefault()之前進行枚舉。 但是,為了將來提供參考,如果該查詢返回了我只希望返回TOP 1的數千行,該怎么辦?

附加信息

使用.FirstOrDefault()的SQL:

SELECT TOP 1 Field1, Field2...
FROM
(
    SELECT SUM(Field) as Field1, ...
    FROM ...
) SUB

使用.ToArray()的SQL:

SELECT SUM(Field) as Field1, ...
FROM ...

直接在SQL Mgt Studio中執行任一操作會在相同的時間內產生相同的結果。 但是,當LINQ執行第一個時,我超時了。

使用linq到sql時,這是一個常見問題。 如果您考慮使用sql,則在進行group by然后是firstordefault時,您是在要求sql進行聚合,然后再進行非聚合。 對於sql來說,很難通過組來處理單個元素,因為它將執行多個查詢以到達單個元素。

當您執行ToArray時,實際上是將數據拉回到內存中,而分組依據實際上是與各個元素一起存儲在內存中的,因此到達這些元素的速度會快得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM