Entity Framework generated really bad SQL when using ANY

妖精的绣舞 提交于 2020-01-26 04:00:07

问题


I'm analyzing the queries that are running in a DB (Azure Sql Server V12) and I found a few queries generated by Entity Framework (EF 6.0) that make no sense to me. They are really bad for performance and I cannot find where they are generated.

(@p__linq__0 nvarchar(4000))SELECT 
    CASE WHEN ( EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[SellerPhone] AS [Extent1]
        WHERE [Extent1].[Phone] = @p__linq__0
    )) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT 
        1 AS [C1]
        FROM [dbo].[SellerPhone] AS [Extent2]
        WHERE [Extent2].[Phone] = @p__linq__0
    )) THEN cast(0 as bit) END AS [C1]
    FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]

Solution: if you have a query like this it means you have EF 6.0 or older and you are doing a simple dbContext.SellerPhones.Any(p => xxx). Just upgrade to 6.1 and the generated query will be much better.


回答1:


To find out where the query is generated, enable the EF Logging (either to the console or your logging framework.) Once you have that turned on, try to find part of the query (like [dbo].[SellerPhone] AS [Extent2]) in your logs, and with the other logs surrounding the query, you should know where you are.

This should help you enable the logging:

public MyContext : DbContext
{
    private static ILog log = LogManager.GetCurrentClassLogger();

    public MyContext(string connectionString)
        : base(connectionString)
    {
        this.Database.Log = (msg) => log.Trace(msg);
    }
}



回答2:


I did what Tipx described but I also added the stack trace to be able to know which method was generating each query:

Database.Log = (sql => 
            {
                System.Diagnostics.Debug.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
                System.Diagnostics.Debug.WriteLine(sql);
            });

In EF 6.0, a simple query like dbContext.SellerPhones.Any(p => condition) will generate an ugly query that has a CASE and calls the EXISTS twice.

After upgrading to EF 6.1 the query has only ONE EXISTS and performs much better (I highlighted below that part of the generated query that was updated).

SELECT CASE WHEN ( EXISTS (SELECT 1 AS [C1] FROM [dbo].[SellerPhone] AS [Extent1] WHERE [Extent1].[Phone] = @p__linq__0 )) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C1] FROM ( SELECT 1 AS X ) AS [SingleRowTable1]



来源:https://stackoverflow.com/questions/43684008/entity-framework-generated-really-bad-sql-when-using-any

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!