在实体框架中执行Include()时?

时间:2017-02-02 15:09:27

标签: c# entity-framework

我有一个简单的问题,但没有找到答案 如果我这样做

var result = _db.Table.Include(t => t.Child).Where(t => t.Id == id).Single();

join正在通话时? 在它发现我的实体或它包含SQL期间寻找行的每个孩子后? 让我们看看基于简单数据库模型的示例:

public class Head
{
    //... columns
    public virtual Child {get; set;}
    public Guid? ChildId {get; set;}
}
void main()
{
    //The first version of code
    var child = _db.Head.Include(h => h.Child)
        .FirstOrDefault(//boring staff but we don't need child here)
        ?.Child;
    if (child != null)
        foo(child);
    //The second one
    var head = _db.Head.FirstOrDefault(//boring staff);
    if (head != null && head.ChildId.HasValue)
        foo(head.Child); // I know here we make a new request to our db
}

哪两个选项更有效率? 当我只需要一个基于父表的过滤器查询的对象时,我担心“通过SQL加载额外的子项” 提前谢谢!

2 个答案:

答案 0 :(得分:1)

它将首先评估where条件。不是在C#中,而是在生成的SQL中。 这将生成类似

的SQL
SELECT top 1 .... FROM Table t
JOIN Child c ....
WHERE t.Id = id

您的数据库服务器将创建一个执行计划,该计划将查找索引中的项目并获取相应的子项。

答案 1 :(得分:1)

如果没有IncludeChild个对象的加载会延迟到您需要它们为止。因此,如果您要像这样迭代父/子组

foreach (var parent in _db.Table.Include(t => t.Child).Where(p => p.Name.StartsWith("Q")))
    foreach (var child in parent.Child)
        Console.WriteLine($"{child}, child of {parent}");

往返次数将等于父母加一次。

如果您使用Include,则所有Child个对象都会与父对象一起加载,而不会为每个父对象单独进行往返。因此,上述代码的数据库往返次数将等于1.

Single的情况下,可以按如下方式重写

var result = _db.Table.Include(t => t.Child).Single(t => t.Id == id);

往返次数为Include为1,而Include为2。