我有一个简单的问题,但没有找到答案 如果我这样做
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加载额外的子项” 提前谢谢!
答案 0 :(得分:1)
它将首先评估where条件。不是在C#中,而是在生成的SQL中。 这将生成类似
的SQLSELECT top 1 .... FROM Table t
JOIN Child c ....
WHERE t.Id = id
您的数据库服务器将创建一个执行计划,该计划将查找索引中的项目并获取相应的子项。
答案 1 :(得分:1)
如果没有Include
,Child
个对象的加载会延迟到您需要它们为止。因此,如果您要像这样迭代父/子组
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。