【问题标题】:Why is Entity Framework adding so much onto my query?为什么实体框架在我的查询中添加了这么多?
【发布时间】:2017-04-28 15:26:35
【问题描述】:

我正在构建一个 IQueryable。当我通过 Entity Framework 运行它时,它需要 2.5 秒才能运行。当我抓取查询并运行它,或者只是分析数据库并查看 EF 运行的查询时,它需要

我尝试了 AsNoTracking(),将 LazyLoadingEnabled 关闭...

编辑:针对 results.ToString() 运行秒表所需的时间与运行查询本身一样长(甚至连续运行 .ToString() 2x)所以看起来我需要减少生成查询所需的时间自己。

查询,如 SQL 分析器所见。最新执行时间,87ms:

SELECT 
[Project3].[C1] AS [C1], 
[Project3].[loan_number] AS [loan_number], 
[Project3].[cifno] AS [cifno], 
[Project3].[cifnumber] AS [cifnumber], 
[Project3].[curr_maturity_date] AS [curr_maturity_date], 
[Project3].[total_past_due_balance] AS [total_past_due_balance], 
[Project3].[userdef02] AS [userdef02], 
[Project3].[userdef05] AS [userdef05], 
[Project3].[transaction_amount] AS [transaction_amount], 
[Project3].[user_reference] AS [user_reference], 
[Project3].[effective_date] AS [effective_date], 
[Project3].[userdef03] AS [userdef03], 
[Project3].[userdef01] AS [userdef01], 
[Project3].[acctrefno] AS [acctrefno], 
[Project3].[userdef04] AS [userdef04], 
[Project3].[transrefno] AS [transrefno], 
[Project3].[C2] AS [C2], 
[Project3].[paid_date] AS [paid_date], 
[Project3].[check_number] AS [check_number], 
[Project3].[transaction_amount1] AS [transaction_amount1]
FROM ( SELECT 
    [Filter1].[transrefno] AS [transrefno], 
    [Filter1].[acctrefno1] AS [acctrefno], 
    [Filter1].[effective_date] AS [effective_date], 
    [Filter1].[transaction_amount] AS [transaction_amount], 
    [Filter1].[user_reference] AS [user_reference], 
    [Filter1].[userdef01] AS [userdef01], 
    [Filter1].[userdef03] AS [userdef03], 
    [Filter1].[userdef04] AS [userdef04], 
    [Filter1].[userdef05] AS [userdef05], 
    [Extent6].[loan_number] AS [loan_number], 
    [Extent9].[cifno] AS [cifno], 
    [Extent13].[cifnumber] AS [cifnumber], 
    [Extent16].[curr_maturity_date] AS [curr_maturity_date], 
    [Extent19].[total_past_due_balance] AS [total_past_due_balance], 
    [Extent23].[userdef02] AS [userdef02], 
    [Extent46].[paid_date] AS [paid_date], 
    [Extent50].[check_number] AS [check_number], 
    [Limit21].[transaction_amount] AS [transaction_amount1], 
    1 AS [C1], 
     CAST( [Filter1].[transaction_code] AS int) AS [C2]
    FROM                                (SELECT [Extent3].[transrefno] AS [transrefno], [Extent3].[acctrefno] AS [acctrefno1], [Extent3].[transaction_code] AS [transaction_code], [Extent3].[effective_date] AS [effective_date], [Extent3].[transaction_amount] AS [transaction_amount], [Extent3].[user_reference] AS [user_reference], [Extent3].[userdef01] AS [userdef01], [Extent3].[userdef02] AS [userdef02], [Extent3].[userdef03] AS [userdef03], [Extent3].[userdef04] AS [userdef04], [Extent3].[userdef05] AS [userdef05]
        FROM   [dbo].[loanacct] AS [Extent1]
        INNER JOIN [dbo].[cif] AS [Extent2] ON [Extent1].[cifno] = [Extent2].[cifno]
        INNER JOIN [dbo].[loanacct_trans_history] AS [Extent3] ON [Extent1].[acctrefno] = [Extent3].[acctrefno]
        WHERE ([Extent2].[cifnumber] IN ('647077')) AND ([Extent3].[userdef03] IN ('sizt7c2IokaTKwQCbdXyaw==', '2VnYfyKBwESZtVhXdXxfXg==', 'sizt7c2IokaTKwQCbdXyaw==', 'sizt7c2IokaTKwQCbdXyaw==', '9CR/EFNaFUqPEx3V/WRVww==')) AND ([Extent3].[userdef03] IS NOT NULL) ) AS [Filter1]
    OUTER APPLY  (SELECT TOP (1) [Extent4].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent4]
        INNER JOIN [dbo].[loanacct] AS [Extent5] ON [Extent4].[acctrefno] = [Extent5].[acctrefno]
        WHERE ([Extent5].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent4].[userdef02] = [Filter1].[userdef02]) OR (([Extent4].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit1]
    LEFT OUTER JOIN [dbo].[loanacct] AS [Extent6] ON [Filter1].[acctrefno1] = [Extent6].[acctrefno]
    OUTER APPLY  (SELECT TOP (1) [Extent7].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent7]
        INNER JOIN [dbo].[loanacct] AS [Extent8] ON [Extent7].[acctrefno] = [Extent8].[acctrefno]
        WHERE ([Extent8].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent7].[userdef02] = [Filter1].[userdef02]) OR (([Extent7].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit2]
    LEFT OUTER JOIN [dbo].[loanacct] AS [Extent9] ON [Filter1].[acctrefno1] = [Extent9].[acctrefno]
    OUTER APPLY  (SELECT TOP (1) [Extent10].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent10]
        INNER JOIN [dbo].[loanacct] AS [Extent11] ON [Extent10].[acctrefno] = [Extent11].[acctrefno]
        WHERE ([Extent11].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent10].[userdef02] = [Filter1].[userdef02]) OR (([Extent10].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit3]
    LEFT OUTER JOIN [dbo].[loanacct] AS [Extent12] ON [Filter1].[acctrefno1] = [Extent12].[acctrefno]
    LEFT OUTER JOIN [dbo].[cif] AS [Extent13] ON [Extent12].[cifno] = [Extent13].[cifno]
    OUTER APPLY  (SELECT TOP (1) [Extent14].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent14]
        INNER JOIN [dbo].[loanacct] AS [Extent15] ON [Extent14].[acctrefno] = [Extent15].[acctrefno]
        WHERE ([Extent15].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent14].[userdef02] = [Filter1].[userdef02]) OR (([Extent14].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit4]
    LEFT OUTER JOIN [dbo].[loanacct] AS [Extent16] ON [Filter1].[acctrefno1] = [Extent16].[acctrefno]
    OUTER APPLY  (SELECT TOP (1) [Extent17].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent17]
        INNER JOIN [dbo].[loanacct] AS [Extent18] ON [Extent17].[acctrefno] = [Extent18].[acctrefno]
        WHERE ([Extent18].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent17].[userdef02] = [Filter1].[userdef02]) OR (([Extent17].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit5]
    LEFT OUTER JOIN [dbo].[loanacct] AS [Extent19] ON [Filter1].[acctrefno1] = [Extent19].[acctrefno]
    OUTER APPLY  (SELECT TOP (1) [Extent20].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent20]
        INNER JOIN [dbo].[loanacct] AS [Extent21] ON [Extent20].[acctrefno] = [Extent21].[acctrefno]
        WHERE ([Extent21].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent20].[userdef02] = [Filter1].[userdef02]) OR (([Extent20].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit6]
    LEFT OUTER JOIN [dbo].[loanacct] AS [Extent22] ON [Filter1].[acctrefno1] = [Extent22].[acctrefno]
    LEFT OUTER JOIN [dbo].[loanacct_detail] AS [Extent23] ON [Extent22].[acctrefno] = [Extent23].[acctrefno]
    OUTER APPLY  (SELECT TOP (1) [Extent24].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent24]
        INNER JOIN [dbo].[loanacct] AS [Extent25] ON [Extent24].[acctrefno] = [Extent25].[acctrefno]
        WHERE ([Extent25].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent24].[userdef02] = [Filter1].[userdef02]) OR (([Extent24].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit7]
    OUTER APPLY  (SELECT TOP (1) [Extent26].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent26]
        INNER JOIN [dbo].[loanacct] AS [Extent27] ON [Extent26].[acctrefno] = [Extent27].[acctrefno]
        WHERE ([Extent27].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent26].[userdef02] = [Filter1].[userdef02]) OR (([Extent26].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit8]
    OUTER APPLY  (SELECT TOP (1) [Extent28].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent28]
        INNER JOIN [dbo].[loanacct] AS [Extent29] ON [Extent28].[acctrefno] = [Extent29].[acctrefno]
        WHERE ([Extent29].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent28].[userdef02] = [Filter1].[userdef02]) OR (([Extent28].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit9]
    OUTER APPLY  (SELECT TOP (1) [Extent30].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent30]
        INNER JOIN [dbo].[loanacct] AS [Extent31] ON [Extent30].[acctrefno] = [Extent31].[acctrefno]
        WHERE ([Extent31].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent30].[userdef02] = [Filter1].[userdef02]) OR (([Extent30].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit10]
    OUTER APPLY  (SELECT TOP (1) [Extent32].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent32]
        INNER JOIN [dbo].[loanacct] AS [Extent33] ON [Extent32].[acctrefno] = [Extent33].[acctrefno]
        WHERE ([Extent33].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent32].[userdef02] = [Filter1].[userdef02]) OR (([Extent32].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit11]
    OUTER APPLY  (SELECT TOP (1) [Extent34].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent34]
        INNER JOIN [dbo].[loanacct] AS [Extent35] ON [Extent34].[acctrefno] = [Extent35].[acctrefno]
        WHERE ([Extent35].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent34].[userdef02] = [Filter1].[userdef02]) OR (([Extent34].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit12]
    OUTER APPLY  (SELECT TOP (1) [Extent36].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent36]
        INNER JOIN [dbo].[loanacct] AS [Extent37] ON [Extent36].[acctrefno] = [Extent37].[acctrefno]
        WHERE ([Extent37].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent36].[userdef02] = [Filter1].[userdef02]) OR (([Extent36].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit13]
    OUTER APPLY  (SELECT TOP (1) [Extent38].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent38]
        INNER JOIN [dbo].[loanacct] AS [Extent39] ON [Extent38].[acctrefno] = [Extent39].[acctrefno]
        WHERE ([Extent39].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent38].[userdef02] = [Filter1].[userdef02]) OR (([Extent38].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit14]
    OUTER APPLY  (SELECT TOP (1) [Extent40].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent40]
        INNER JOIN [dbo].[loanacct] AS [Extent41] ON [Extent40].[acctrefno] = [Extent41].[acctrefno]
        WHERE ([Extent41].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent40].[userdef02] = [Filter1].[userdef02]) OR (([Extent40].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit15]
    OUTER APPLY  (SELECT TOP (1) [Extent42].[transrefno] AS [transrefno]
        FROM  [dbo].[loanacct_trans_history] AS [Extent42]
        INNER JOIN [dbo].[loanacct] AS [Extent43] ON [Extent42].[acctrefno] = [Extent43].[acctrefno]
        WHERE ([Extent43].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent42].[userdef02] = [Filter1].[userdef02]) OR (([Extent42].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit16]
    OUTER APPLY  (SELECT TOP (1) [Extent44].[voucher_id] AS [voucher_id]
        FROM  [dbo].[loanacct_trans_history] AS [Extent44]
        INNER JOIN [dbo].[loanacct] AS [Extent45] ON [Extent44].[acctrefno] = [Extent45].[acctrefno]
        WHERE ([Extent45].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent44].[userdef02] = [Filter1].[userdef02]) OR (([Extent44].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit17]
    LEFT OUTER JOIN [dbo].[voucher] AS [Extent46] ON [Limit17].[voucher_id] = [Extent46].[voucher_id]
    OUTER APPLY  (SELECT TOP (1) [Extent47].[voucher_id] AS [voucher_id]
        FROM  [dbo].[loanacct_trans_history] AS [Extent47]
        INNER JOIN [dbo].[loanacct] AS [Extent48] ON [Extent47].[acctrefno] = [Extent48].[acctrefno]
        WHERE ([Extent48].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent47].[userdef02] = [Filter1].[userdef02]) OR (([Extent47].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Limit18]
    LEFT OUTER JOIN [dbo].[voucher] AS [Extent49] ON [Limit18].[voucher_id] = [Extent49].[voucher_id]
    LEFT OUTER JOIN [dbo].[disbursement_check] AS [Extent50] ON [Extent49].[check_id] = [Extent50].[check_id]
    OUTER APPLY  (SELECT TOP (1) [Filter21].[transaction_amount], [Filter21].[userdef02], [Filter21].[transrefno1]
        FROM   (SELECT [Extent51].[transaction_amount] AS [transaction_amount], [Extent51].[userdef02] AS [userdef02], [Project1].[transrefno] AS [transrefno1]
            FROM   [dbo].[loanacct_trans_history] AS [Extent51]
            INNER JOIN [dbo].[loanacct] AS [Extent52] ON [Extent51].[acctrefno] = [Extent52].[acctrefno]
            LEFT OUTER JOIN  (SELECT TOP (1) 
                [Extent53].[transrefno] AS [transrefno]
                FROM  [dbo].[loanacct_trans_history] AS [Extent53]
                INNER JOIN [dbo].[loanacct] AS [Extent54] ON [Extent53].[acctrefno] = [Extent54].[acctrefno]
                WHERE ([Extent54].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent53].[userdef02] = [Filter1].[userdef02]) OR (([Extent53].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Project1] ON 1 = 1
            WHERE ([Extent52].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND ([Extent51].[transaction_code] IN (cast(1000 as decimal(18)), cast(1202 as decimal(18)))) ) AS [Filter21]
        LEFT OUTER JOIN  (SELECT TOP (1) 
            [Extent55].[transrefno] AS [transrefno]
            FROM  [dbo].[loanacct_trans_history] AS [Extent55]
            INNER JOIN [dbo].[loanacct] AS [Extent56] ON [Extent55].[acctrefno] = [Extent56].[acctrefno]
            WHERE ([Extent56].[cifno] IN (cast(309 as decimal(18)), cast(641 as decimal(18)), cast(60583 as decimal(18)))) AND (([Extent55].[userdef02] = [Filter1].[userdef02]) OR (([Extent55].[userdef02] IS NULL) AND ([Filter1].[userdef02] IS NULL))) ) AS [Project2] ON 1 = 1
        WHERE ([Filter21].[userdef02] = (CASE WHEN ([Filter21].[transrefno1] IS NULL) THEN N'' ELSE  CAST( [Project2].[transrefno] AS nvarchar(max)) END)) OR (([Filter21].[userdef02] IS NULL) AND (CASE WHEN ([Filter21].[transrefno1] IS NULL) THEN N'' ELSE  CAST( [Project2].[transrefno] AS nvarchar(max)) END IS NULL)) ) AS [Limit21]
)  AS [Project3]
ORDER BY [Project3].[effective_date] DESC
OFFSET 0 ROWS FETCH NEXT 50 ROWS ONLY 

查询的主要部分...调用 ToList() 需要 2.5 秒

            var queryable = ApplyQuery(query, nlsContext);
            var transactionQueryable = queryable.SelectMany(l => l.loanacct_trans_history);

            if (query.UserIds != null)
            {
                var encodedUserIds = query.UserIds.Select(u => GuidEncoder.Encode(u)).ToList();
                transactionQueryable = transactionQueryable.Where(t => encodedUserIds.Contains(t.userdef03));
            }

            if(query.AdvancesOnly)
            {
                transactionQueryable = transactionQueryable.Where(t => AdvanceTypes.Contains(t.transaction_code));
            }

            if (!string.IsNullOrWhiteSpace(query.SortProperty))
            {
                transactionQueryable = ApplySort(nlsContext, transactionQueryable, query);
            }
            else
            {
                transactionQueryable = transactionQueryable.ApplySort(t => t.transaction_reference_no, true);
            }

            transactionQueryable = transactionQueryable.ApplyPaging(query);

            var results = transactionQueryable
                .Select(t => new
                {
                    t,
                    DealerTransaction = nlsContext.loanacct_trans_history
                        .Where(dth => dealerIds.Contains(dth.loanacct.cif.cifno))
                        .Where(dth => dth.userdef02 == t.userdef02)
                        .FirstOrDefault()
                })
                .Select(o => new TransactionHistoryResult
                {
                    Loan = new Loan
                    {
                        AccountNumber = o.t.loanacct.loan_number,
                        ContactId = o.t.loanacct.cifno,
                        ContactNumber = o.t.loanacct.cif.cifnumber,
                        MaturityDate = o.t.loanacct.curr_maturity_date,
                        PastDue = o.t.loanacct.total_past_due_balance,
                        ProgramIdString = o.t.loanacct.loanacct_detail.userdef02,
                    },
                    Transaction = new Transaction
                    {
                        AdminUserId = o.t.userdef05,
                        Amount = o.t.transaction_amount,
                        Comment = o.t.user_reference,
                        EffectiveDate = o.t.effective_date,
                        EncodedUserId = o.t.userdef03,
                        InvoiceNumber = o.t.userdef01,
                        LoanId = o.t.acctrefno,
                        Product = o.t.userdef04,
                        RowId = o.t.transrefno,
                        Type = (Raf.Models.Lending.TransactionType)(int)o.t.transaction_code
                    },
                    PaidDate = o.DealerTransaction.voucher.paid_date,
                    CheckNumber = o.DealerTransaction.voucher.disbursement_check.check_number,
                    CreditServiceFee = nlsContext.loanacct_trans_history
                                    .Where(csfth => CreditServiceFeeTypes.Contains(csfth.transaction_code))
                                    .Where(csfth => dealerIds.Contains(csfth.loanacct.cif.cifno))
                                    .Where(th => th.userdef02 == o.DealerTransaction.transrefno.ToString())
                                    .FirstOrDefault()
                                    .transaction_amount
                });

【问题讨论】:

  • 这是您对数据库运行的第一个查询吗? EF 有一些较大的一次性启动成本,它会在每个 AppDomain 执行一次,这仅在您第一次“接触”数据库后才会发生。
  • 这是使用 EF 的一个缺点。这对你来说很容易,但你会失去控制。这是你失去的一件事,性能。
  • @ScottChamberlain 时间都来自第一次之后的调用
  • 这个查询的一些代码怎么样?
  • @KyleW - 您显示的不是单个查询。 UserId 有一个 .ToList(),然后 CreditServiceFee 上有一个 FirstOrDefault()(每个行都会调用该子查询一次),然后是 DealerTransaction 上的一个子查询。请注意,您发布的 SQL 中没有 DealerTransaction 或 CreditServiceFee。这是因为这些查询是由 EF 单独执行的。此外,您似乎从单独的 EF 上下文中获取 CreditServiceFee 和 DealerTransaction 的信息。这意味着不同的数据库。这也使数据的组装变得复杂。

标签: c# entity-framework


【解决方案1】:

“当我抓取查询并运行它时”

当您从 Sql Server Management Studio 运行查询时,您使用的是其默认的查询执行设置,不一定与实体框架 (ado.net) 使用的设置相同。

在 Sql Manager 中,您可以检查

下的默认设置

工具/选项/查询执行/SQL Server

因此,如果您想正确评估查询,则需要从分析器中获取连接设置,并在从 sql management studio 执行时为查询设置相同的选项。

【讨论】:

  • 使用分析器无法正确评估查询?
  • @Kylew Sql Profiler 可以评估 Sql 中的查询。这就是 C#、LINQ 和 EF 如何尝试找出如何编写 SQL,然后在收到数据后如何组装它,这会让你放慢速度
  • @MadMyche 我同意,这就是我想要找出的。这个答案说我需要用不同的连接字符串测试查询,这不会影响它
  • 并非如此,更多的是尝试让连接字符串和参数与 Query Profiler 正在运行的相同;连接和命令的设置方式比 DS、UN 和 PW 更多。我仍然希望尽可能多地从 LINQ 中获取这些内容并尽可能多地进入 View 或 SP,
【解决方案2】:

查询执行后的下一步是对象实现,其中从 SQL 检索到的表数据被转换为单个对象。

SQL 会发送一个包含大量重复值的大表,并且 SQL 会快速发送它,可能与您向 Sql server 请求原始 sql 的时间相同,但是 EF 的实现速度很慢,并且随着许多嵌套而变得越来越慢选择。

由于您的查询的选择具有嵌套选择,这将需要一些时间,因为 EF 必须在内存中执行 group by 并执行一些内存查询以构建您请求的图形格式的对象。

当您说查询是 82 毫秒时,分析您的 C# 代码将揭示它花费大部分时间的位置。

.GroupBy(q => 0) 之类的东西是性能杀手,因为 EF 无法将其转换为 SQL group by,但由于前面有很多复杂的语句,它将在内存 group by 中执行。

在这种情况下,我们可以简单地创建一个视图和/或存储过程来创建简单的表,该表可以映射到一个实体中的简单属性。 EF 不是设计的,也不推荐作为存储过程和 SQL 的替代品。

【讨论】:

  • 谢谢。该代码中的 GroupBy 实际上与相关查询分开运行并快速返回。我正在删除那部分代码,因为它不涉及。我将尝试分析 C# 代码,看看我可以深入研究多远。您提到了嵌套选择,但这似乎由数据库运行得很好,并且没有分组。即使我当前示例中的 groupby 不是此查询的一部分,分组仍然会在客户端完成吗?
  • 我完全赞成创建 SP 或视图并让 EF 访问它...让 EF 在这样的查询中失败,尤其是在“代码优先”环境中,就像让 FrontPage 构建您的数据库访问在网站上
  • @MadMyche - 我不同意。 EF 查询可能非常高效,但您通常需要了解它在内部如何工作以构建高效查询。很多人尝试像构建 SQL 一样构建查询,但结果并不总是很好。
  • @ErikFunkenbusch 我不同意,EF 效率不高。任何分析工具都会告诉你这一点。
  • @jdmdevdotnet - 这一点完全超出了您的想象。是的,任何分析工具都会告诉您构建效率低下的 EF 查询效率低下。呵呵。
猜你喜欢
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2014-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多