C# 为什么EF提取所有记录,然后通过PK再次提取所有记录

C# 为什么EF提取所有记录,然后通过PK再次提取所有记录,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我有下面的EF6文件 dgOrders.DataSource = Context.Orders .Where(o => o.ProposedOrder == ProposedOrders && o.Inactive == false && o.OnHold == false && o.Archive == fa

我有下面的EF6文件

       dgOrders.DataSource = Context.Orders
            .Where(o => o.ProposedOrder == ProposedOrders
                && o.Inactive == false
                && o.OnHold == false
                && o.Archive == false
                && (!o.ManufactureSiteFlag.HasValue || (o.ManufactureSiteFlag & currentSite) > 0)
                && (FilterOnDispatch == "" 
                    || (FilterOnDispatch.Equals("YES") && o.Deliveries.Count(d => d.Dispatched == true) > 0)
                    || (FilterOnDispatch.Equals("NO") && o.Deliveries.Count(d => d.Dispatched == false) > 0)));
当它执行时,会在服务器上生成以下SQL序列

(@p__linq__0 bit,@p__linq__1 int,@p__linq__2 nvarchar(4000),@p__linq__3 nvarchar(4000),@p__linq__4 nvarchar(4000))
SELECT 
[Project3].[OrderID] AS [OrderID], 
[Project3].[OrderNum] AS [OrderNum], 
....
[Project3].[OrderDeliveryStatusID] AS [OrderDeliveryStatusID]
FROM ( SELECT 
    [Project2].[OrderID] AS [OrderID], 
    [Project2].[OrderNum] AS [OrderNum], 
    ....
    [Project2].[OrderDeliveryStatusID] AS [OrderDeliveryStatusID]
    FROM ( SELECT 
        [Project1].[OrderID] AS [OrderID], 
        [Project1].[OrderNum] AS [OrderNum], 
        ....
        [Project1].[OrderDeliveryStatusID] AS [OrderDeliveryStatusID], 
        [Project1].[C1] AS [C1], 
        (SELECT 
            COUNT(1) AS [A1]
            FROM [dbo].[Deliveries] AS [Extent3]
            WHERE ([Project1].[OrderID] = [Extent3].[OrderID]) AND (0 = [Extent3].[Dispatched])) AS [C2]
        FROM ( SELECT 
            [Extent1].[OrderID] AS [OrderID], 
            [Extent1].[OrderNum] AS [OrderNum], 
            ....
            [Extent1].[OrderDeliveryStatusID] AS [OrderDeliveryStatusID], 
            (SELECT 
                COUNT(1) AS [A1]
                FROM [dbo].[Deliveries] AS [Extent2]
                WHERE ([Extent1].[OrderID] = [Extent2].[OrderID]) AND (1 = [Extent2].[Dispatched])) AS [C1]
            FROM [dbo].[Orders] AS [Extent1]
        )  AS [Project1]
    )  AS [Project2]
    WHERE ([Project2].[ProposedOrder] = @p__linq__0) AND (0 = [Project2].[Inactive]) AND (0 = [Project2].[OnHold]) AND (0 = [Project2].[Archive]) AND (([Project2].[ManufactureSiteFlag] IS NULL) OR ((( CAST( [Project2].[ManufactureSiteFlag] AS int)) & (@p__linq__1)) > 0)) AND ((N'' = @p__linq__2) OR ((N'YES' = @p__linq__3) AND ([Project2].[C1] > 0)) OR ((N'NO' = @p__linq__4) AND ([Project2].[C2] > 0)))
)  AS [Project3]
然后产生

SELECT 
[Extent1].[OrderID] AS [OrderID], 
[Extent1].[OrderNum] AS [OrderNum], 
...
[Extent1].[OrderDeliveryStatusID] AS [OrderDeliveryStatusID]
FROM [dbo].[Orders] AS [Extent1];

SELECT 
[Extent1].[OrderID] AS [OrderID], 
[Extent1].[OrderNum] AS [OrderNum], 
....
[Extent1].[OrderDeliveryStatusID] AS [OrderDeliveryStatusID]
FROM [dbo].[Orders] AS [Extent1]
WHERE [Extent1].[OrderID] IN (91,181,421,690,844,1544,2460,2682,2687,2736,2760,2806,2816,2817,2818,3134,3141,3154,3473,3726,4404,4583,4590,4641,4673,4677,4695,4737,4741,4789,4837,4885,4886,4887,4889,4993,5013,5018,5043,5046,5074,5090,5106,5134,5141,5231,5260,5261,5264,5265,5276,5369,5371,5421,5458,5513,5583,5688,5837,5863,5894,5895,5908,6002,6055,6084,6113,6128,6240,6432,6589,6590,6651,6676,6708,6733,6757,6772,6785,6831,6931,6934,6935,6936,7003,7004,7043,7068,7128,7135,7170,7172,7195,7223,7243,7325,7350,7360,7377,7452,7504,7508,7568,7613,7614,7641,7676,7714,7740,7764,7842,8008,8023,8174,8244,8250,8269,8312,8340,8346,8392,8437,8470,8488,8652,8664,8703,8710,8722,8750,8831,8920,9016,9181,9243,9262,9413,9421,9429,9621,9680,9707,9709,9710,9772,9787,9797,9832,9911,9918,9959,9961,9972,10042,10052,10056,10083,10120,10189,10221,10222,10253,10254,10293,10348,10413,10415,10430,10442,10452,10468,10491,10505,10529,10555,10573,10630,10662,10787,10791,10804,10838,10887,10933,10934,10955,10968,11010,11020,11059,11072,11078,11149,11151,11188,11281,11299,11421,11496,11502,11572,11647,11655,11758,11817,11948,12049,12082,12137,12201,12275,12406,12451,12466,12472,12516,12547,12581,12608,12650,12666,12720,12730,12732,12771,12775,12792,12807,12810,12843,12965,13074,13075,13085,13087,13102,13153,13198,13316,13326,13516,13763,13795,13800,13802,13867,13871,13878,13887,13891);
第二条SQL语句使用不同的主键值重复多次

为什么第一个select语句不足以满足请求的要求。随后的一组语句似乎返回了数据集的缩小视图,没有任何额外的好处

它是否与外键链接有关

在这里可以做些什么来提高性能


更新:除了采用下面的一些注释和答案来提高原始查询的性能外,还将额外的回迁跟踪到上下文。由于某种原因,刷新选项是这种行为的始作俑者。

如果您使用参数来打开或关闭部分查询,您应该编写它,而不是将它放在查询本身中。这将简化查询本身

var query = Context.Orders
        .Where(o => o.ProposedOrder == ProposedOrders
            && o.Inactive == false
            && o.OnHold == false
            && o.Archive == false
            && (!o.ManufactureSiteFlag.HasValue || (o.ManufactureSiteFlag & currentSite) > 0);

if (FilterOnDispatch.Equals("YES"))
    query = query.Where(o=>o.Deliveries.Count(d => d.Dispatched == true) > 0);
else if (FilterOnDispatch.Equals("NO"))
    query = query.Where(o=>o.Deliveries.Count(d => d.Dispatched == false) > 0);

dgOrders.DataSource = query;

此外,查询中是否包含任何实体?后续查询可能是由于EF必须将相关实体拉到主实体旁边造成的。

我真的不知道您发布的代码如何生成SQL,因为您的查询中没有任何内容测试OrderID,更不用说.Contains了(这将是生成in的依据)。仅供参考,.Any()的性能将优于.Count()>0,因为.Count必须在存在任何使用时对所有记录进行计数,这将在找到第一条记录后返回。您使用正确的第一条语句进行了正确更新。对于复杂的查询,第一条语句是非常标准的。多个子选择已优化,无需担心。同样,第二组查询我看不出它们之间有什么关联。必须使用.Contains()方法才能生成IN子句。您确定这不是辅助查询吗?还是在后面的语句中向第一个查询添加其他表达式?我不知道。它可能是导致生成的DevExpress网格中某些列的副产品。我仍在努力掌握表单代码库中的内容。我敢打赌它是。。。网格可能使用分页,这将创建一个IN子句来选择记录子集以查看一页数据。这应该很容易找到。。。只需注释掉网格,并对查询执行.ToList()即可执行它并查看实际的查询结果。它可能也在做未过滤列表的工作,这样它就可以获得记录id和行数的列表。是否有任何方法可以获得任何后续查询,并将原始源记录在某处?@sweetfa你是什么意思?这些查询与SQL server上执行的查询相同。我想将查询追溯到原始源代码中的点。是否有一个标志可以打开以启用与原始源代码命令相关的SQL日志记录。我可以看到服务器上发生了什么,但我无法判断哪段代码首先生成SQLplace@sweetfa-您可能需要查看EF profiler,或者是单机版,或者是类似“一瞥”的东西。