实体框架/ SQL Server包含过滤行为

时间:2015-07-05 15:47:17

标签: sql-server entity-framework

我有两个关于EF和SQL Server的基本问题,我会问一些例子。

  1. 说我有以下查询:

    db.Customers.Include(c => c.Orders)
            .Include(c => c.Items)
            .Include(....).Where(c => c.Age > 25)
    

    在这个简单的查询中,我根据某些条件检索客户,并从其他表中获取一些相关数据。包含(连接)是否会首先发生在数据库中的所有记录上,然后这些将在条件下进行过滤,首先引擎将过滤记录而不加入任何内容,然后仅在过滤时执行连接记录?关于将作为查询生成的内容以及SQL Server查询引擎,此问题与EF有关。

  2. 如果包含中使用的某些属性是过滤的一部分,那么行为会是什么?将再次所有联接对数据库中的每个记录执行它将仅执行所需的联接以过滤数据库中的所有记录,然后仅执行剩余的联接在过滤的记录?情况可以描述如下:

    db.Customers.Include(c => c.Orders)
            .Include(c => c.Items)
            .Include(....).Where(c => c.Orders.Any(o.Name.StartsWith("Football")
    

    如果过滤中没有使用导航属性(如问题1所示),行为如何不同?

1 个答案:

答案 0 :(得分:3)

不,Include不会根据您提供的过滤器过滤相关对象。因为两者都是不同的操作。在这种情况下,您将不得不使用预测。

db.Customers.Include(c => c.Orders)
    .Include(c => c.Items)
    .Include(....).Where(c => c.Orders.Any(o.Name.StartsWith("Football")

以上查询将给出不同的结果,然后使用Projection进行查询,如下所示,

db.Customers
    .Include(c => c.Items)
    .Include(....).Select(c => new {
         Customer = c,
         Orders = c.Orders.Where( o => o.Name.StartsWith("Football")
    })

我已移除包含订单,但我已为订单创建了投影。

在第一种情况下,WHERE子句没有连接,但它将使用EXISTS子句,对于Include,它将使用Join来获取所有记录。

在第二种情况下,它将执行连接以获得带过滤器的结果,因此它只会在投影中指定的过滤器上执行连接。