简体   繁体   English

查找实体然后附加关系数据与使用Include然后使用FirstOrDefault

[英]Finding an entity then attaching relational data vs. using Include and then FirstOrDefault

Considering a table [Person] which has two foreign keys ( [Phone_Numbers] , [Business_Information] ). 考虑具有两个外键的表[Person][Phone_Numbers][Business_Information] )。 When using EF Core, we can simply find a Person using the dbContext.Find method like var person = await db.Context.FindAsync<Person>(1) ; 使用EF Core时,我们可以使用dbContext.Find方法找到一个Person ,如var person = await db.Context.FindAsync<Person>(1) ; however, the Find method only looks for the entity inside the tracking cache and it does not handle relational properties. 但是, Find方法仅查找跟踪缓存中的实体,并且它不处理关系属性。 In order to solve this, we can call the Entry method to attach those properties like dbContext.Entry<Person>(person).Reference(x=> x.Business_Information) . 为了解决这个问题,我们可以调用Entry方法来附加dbContext.Entry<Person>(person).Reference(x=> x.Business_Information) Considering the provided example, we have to call the Entry method twice in this case: 考虑到提供的示例,在这种情况下我们必须调用两次Entry方法:

dbContext.Entry<Person>(person).Reference(x=> x.Business_Information).Load();
dbContext.Entry<Person>(person).Collection(x=> x.Phone_Numbers).Load();

An alternative solution is to use the Include method: 另一种解决方案是使用Include方法:

var person = await dbContext.Set<Person>().Include("Business_Information").Include("Phone_Numbers").FirstOrDefaultAsync(x=> x.id == id);

The first solution sends two request to the Db (I think the Find method does not send a request if the entity is being tracked); 第一个解决方案向Db发送两个请求(我认为如果正在跟踪实体, Find方法不会发送请求); however, I'm not sure how the second one works and accordingly I'm also unsure if it has any performance advantages. 但是,我不确定第二个是如何工作的,因此我也不确定它是否有任何性能优势。 I've been thinking the first solution could be faster and more efficient. 我一直在想第一个解决方案可以更快,更有效。 I'd appreciate if someone clarifies this for me. 如果有人为我澄清这一点,我会很感激。

It really depends on number of related properties, their type (reference or collection) and in the first case - if they are already loaded or not. 它实际上取决于相关属性的数量,它们的类型(引用或集合)以及第一种情况 - 如果它们已经加载或不加载。

Let say your entity has N reference navigation properties and M collection navigation properties that you want to load. 假设您的实体具有您要加载的N个参考导航属性和M个集合导航属性。

The approach with Include will always execute 1 + M db queries - one for the entity + reference properties which data is retrieved with JOIN s to the corresponding tables and returned as columns in the query result) and one for each collection - regardless of whether the entity and any of the related entities/collections is already loaded. 使用Include的方法将始终执行1 + M db查询 - 一个用于实体+引用属性,其中数据通过JOIN检索到相应的表并在查询结果中作为列返回),每个集合一个 - 无论是否实体和任何相关实体/集合已加载。

The approach with explicit loading is more dynamic. 显式加载的方法更具动态性。

It will execute 1 db query for the entity if it's not loaded in the context, 0 otherwise. 如果实体未在上下文中加载,它将对该实体执行1 db查询,否则为0。

For each reference navigation property it will execute 1 db query if the referenced entity is not already loaded in the context, 0 otherwise. 对于每个引用导航属性,如果引用的实体尚未在上下文中加载,则它将执行1 db查询,否则为0。

For each collection navigation property, it will execute 1 db query if the collection is not marked as loaded ( db.Entry(entity).Collection(e => e.Collection).IsLoaded == false ), 0 otherwise. 对于每个集合导航属性,如果集合未标记为已加载,则它将执行1 db查询( db.Entry(entity).Collection(e => e.Collection).IsLoaded == false ),否则为0。

At the end, the explicit loading approach could execute between 0 and 1 + N + M db queries. 最后,显式加载方法可以在01 + N + M db查询之间执行。

With all that being said, it's not clear which one is better. 尽管如此,目前还不清楚哪一个更好。 If you are using relatively short lived DbContext instances, hence the chances of not execution related queries is low, I would go with Include approach because it is deterministic. 如果你使用相对短命的DbContext实例,因此不执行相关查询的可能性很低,我会采用Include方法,因为它是确定性的。

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

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