简体   繁体   English

使用EF,多次选择或使用包含时哪个更好?

[英]Which is better when using EF, select multiple times or using include?

I have two entities, one is box and the other is tennis . 我有两个实体,一个是box ,另一个是tennis There is a foreign key BoxID in table tennis , that is to say, a tennis must be in a box , and the box is a collection of tennis . tennis有一个外键BoxID ,也就是说, box必须装有tennis ,而boxtennis的集合。

Now that I know a tennis ID , I need to check the name of the box to which this tennis belongs. 现在我知道了tennis ID ,我需要检查该tennis所属的boxname I have two options. 我有两个选择。

Option A: First find the attribute of this tennis in the tennis table, get the BoxID , and then go to the box table to find the attribute of the box . 选项A:首先找到这个的属性tennistennis表,拿到BoxID ,然后转到box表中查找的属性box

var tennisId = 12345;

// Option A:
var tennis = await dbContext.TennisTable
        .SingleOrDefaultAsync(t => t.Id == tennisId);

var box = await dbContext.BoxTable
        .SingleOrDefaultAsync(t => t.Id == tennis.BoxID);

return box.Name;

Option B: Directly use the Include syntax of EF Core to find the tennis and the box to which it belongs, to get the properties of the box . 选项B:直接使用EF CoreInclude语法查找tennis及其所属的box ,以获取box的属性。

// Option B:

var tennis = await dbContext.TennisTable
        .Include(t => t.Box);
        .SingleOrDefaultAsync(t => t.Id == tennisId);

return tennis.Box.Name;

In the large-scale practice, which of the above two methods has more performance advantages? 在大规模实践中,以上两种方法中哪一种具有更大的性能优势?

large-scale means that the questions may be much more complicated in real use cases. large-scale意味着问题在实际用例中可能要复杂得多。 The count of box and tennis may be billions. 的计数boxtennis可能是数十亿美元。

Neither. 都不行 You don't need an Include statement here. 您不需要在此处Include语句。

The Include statement should be used when you want to retrieve additional related entities . 检索其他相关实体时,应使用Include语句。 But that is not what you want: 但这不是您想要的:

I need to check the name of the box to which this tennis belongs. 我需要检查此网球所属的框的名称。

You only need the Box object to read its name. 您只需要Box对象来读取其名称。 You don't need to load any additional entities. 您不需要加载任何其他实体。

var boxName = db.TennisTable
                .Where(t => t.Id == tennisId)
                .Select(t => t.Box.Name)
                .Single();

If you need to account for the tennis object possibly not existing without throwing an exception, use SingleOrDefault() instead of Single() . 如果需要在不引发异常的情况下考虑可能不存在的网球对象,请使用SingleOrDefault()而不是Single()

In other words: 换一种说法:

  • Find all tennis objects with this ID . 查找所有具有此ID的网球对象 We know there is only one, but by using Where instead of Single , EF does not yet query the database and it can keep using an IQueryable instead. 我们知道只有一个,但是通过使用Where而不是Single ,EF尚未查询数据库,它可以继续使用IQueryable
  • For all found entries, select the name of its box . 对于找到的所有条目, 选择其框的名称 Again, we know there's one entry, but EF will still not instantiate the query because you're not enumerating the IQueryable yet. 同样,我们知道只有一个条目,但是EF仍不会实例化查询,因为您尚未枚举IQueryable
  • Take the first result . 取得第一个结果 We know it's the only result, but now EF will hit the database with a single (combined) call instead of two separate ones. 我们知道这是唯一的结果,但是现在EF将通过单个(组合)调用而不是两个单独的调用访问数据库。

If you had used Include logic, you would've retrieved the entire tennis and box objects. 如果使用了“ Include逻辑,则将检索到整个网球和框对象。 My answer only retrieves the box name, which is a significant reduction of data transfer size between the database and your application. 我的答案仅检索框名,这大大减少了数据库和应用程序之间的数据传输大小。

If you had used two calls, you would've loaded both the tennis and box object and you would've had to do two calls, which means increased data transfer size and lowered performance due to additional network calls. 如果使用了两次通话,则将同时加载网球对象和盒子对象, 并且必须进行两次通话,这意味着由于进行了额外的网络通话,因此增加了数据传输大小降低了性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM