实体框架 – EF6 SQL生成

前端之家收集整理的这篇文章主要介绍了实体框架 – EF6 SQL生成前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
尝试从EF5升级到EF6,我可以通过可空列显示性能差距查找表.以下是一个示例:
public class Customer
{
    public int Id { get; set; }
    public int? ManagerId { get; set; }
    //public virtual Manager Manager { get; set; }
}

public class MyContext : DbContext
{
    public MyContext(string connstring): base(connstring){}
    public DbSet<Customer> Customers { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var db = new MyContext("CONNSTRING");
        var managerId = 1234;
        var q = from b in db.Customers
                where b.ManagerId == managerId
                select b.Id;
        var s = q.ToString();
    }
}

当EF6生成sql时,它为空处理添加了一些逻辑:

SELECT 
[Extent1].[Id] AS [Id]
FROM [dbo].[Customers] AS [Extent1]
WHERE (([Extent1].[ManagerId] = @p__linq__0) 
AND ( NOT ([Extent1].[ManagerId] IS NULL OR @p__linq__0 IS NULL))) 
OR (([Extent1].[ManagerId] IS NULL) AND (@p__linq__0 IS NULL))

注意同样的linq在EF5下生成更简单的sql

SELECT 
[Extent1].[Id] AS [Id]
FROM [dbo].[Customers] AS [Extent1]
WHERE [Extent1].[ManagerId] = @p__linq__0

我可以理解开发人员试图实现的一点:如果提供null作为参数,那么managerId = null的查询将不会选择任何行.我感谢关心,但99.9%的搜索逻辑是分开的:一个usecase寻找ManagerId == null的位置,另一个搜索特定的id,其中ManagerId == managerId

问题是性能影响很大:MS sql不会在ManagerId上使用索引,而是发生表扫描.我的项目有几百个类似的搜索,数据库大小约100GB的整体性能,升级到EF6大约10.

问题是有没有人知道某种配置或约定在EF6中禁用此路障并生成简单的sql

编辑:

我在我的项目中检查了十几个类似的选择,发现:

>在某些情况下,sql SERVER使用为字段I指定的索引
搜索.即使在这种情况下也有轻微的性能损失:它
使用索引两次:第一次查找我指定的值
参数,第二次寻找null
>当常数被精确地指定为非空时,EF6甚至检查null,例如:

from p in db.PtnActivations
        where p.Carrier != "ALLTEL"
        where p.Carrier != "ATT"
        where p.Carrier != "VERIZON"

生成sql

WHERE ( NOT (('ALLTEL' = [Extent1].[Carrier]) AND ([Extent1].[Carrier] IS NOT NULL))) AND ( NOT (('ATT' = [Extent1].[Carrier]) AND ([Extent1].[Carrier] IS NOT NULL))) AND ( NOT (('VERIZON' = [Extent1].[Carrier]) AND ([Extent1].[Carrier] IS NOT NULL)))

没有利用我的载体索引. EF5版本

( NOT (('ALLTEL' = [Extent1].[Carrier]))) AND ( NOT (('ATT' = [Extent1].[Carrier]))) AND ( NOT (('VERIZON' = [Extent1].[Carrier]) ))

利用它.

注意条件(‘ALLTEL’= [Extent1].[Carrier])AND([Extent1].[Carrier] IS NOT NULL).第二部分总是假的,但是添加这个部分就放弃了索引.

我经常进口大约1.7M的记录(通常需要约30分钟),持续3个小时,进度约为30%.

解决方法

db.Configuration.UseDatabaseNullSemantics = true;

以获得您在EF5中的行为.这个workitem描述了真假之间的区别是什么,应该帮助你确定你是否符合旧的行为.

猜你在找的MsSQL相关文章