简体   繁体   English

实体框架 - 通用预加载(包括字符串)缺失级别

[英]Entity Framework - generic eager loading (include string) missing levels

My database contains a Vendor, Project,Address and Vendor_Project tables.我的数据库包含 Vendor、Project、Address 和 Vendor_Project 表。 Every Vendor has an address.每个供应商都有一个地址。 I wrote a generic function that performs include to the levels received from input.我写了一个通用的 function 执行包含从输入接收到的级别。

string[] includes = {"Vendor","Project"};
IEnumerable<Vendor_Project> vendorsOfProject = (IEnumerable<Vendor_Project>) await DataStore.Instance.vendorProjectsService.GetAll(includes);


public async Task<IEnumerable<T>> GetAll(string[] includes = null)
        {
            using (DeployToolDBContex contex = _contexFactory.CreateDbContext())
            {
                var query = contex.Set<T>().AsQueryable();
                foreach (var include in includes)
                    query = query.Include(include);
                return query.ToList();
            }
        }

In the above example I got the requested result but the address is null. How can i make that query worked for all levels and their sub levels?在上面的示例中,我得到了请求的结果,但地址是 null。我如何才能使该查询适用于所有级别及其子级别?

For EF6 you would need to specify each child & grandchild as part of your Includes list, so {"child", "child.grandchild"} .对于 EF6,您需要将每个孩子和孙子指定为包含列表的一部分,因此{"child", "child.grandchild"} For EF Core you will probably need to parse to perform an Include and ThenInclude and potential further levels of ThenInclude chaining down.对于 EF Core,您可能需要解析以执行IncludeThenInclude以及潜在的进一步级别的ThenInclude链接。

I would highly recommend reconsidering the approach where you feel you need Includes on something like a GetAll method.我强烈建议您重新考虑您认为需要包含在 GetAll 方法之类的东西上的方法。 Instead, consider leveraging Projection to transform an entity graph down to a ViewModel with details from the entity and related entities.相反,考虑利用 Projection 将实体图向下转换为包含实体和相关实体详细信息的 ViewModel。 The problem with particularly Generic patterns like this is that you are committing to materializing a potentially huge portion of your database into memory. When fetching lists of entities you generally do not need every field from every related entity, but rather a few important fields/keys, and possibly some summary details or counts etc. from related entities.像这样的特别通用模式的问题在于,您正在致力于将数据库的很大一部分具体化为 memory。在获取实体列表时,您通常不需要每个相关实体的每个字段,而是一些重要的字段/键,以及可能来自相关实体的一些摘要详细信息或计数等。

Where you may typically still need to eager load related entities would be when fetching a single top-level entity with it's assortment of related entities such as to present a detailed view.当获取单个顶级实体及其相关实体的分类时,您通常可能仍然需要急切加载相关实体,例如呈现详细视图。 For EF Core when you do have a legitimate case to eager load a lot of entities like nested child collections, you should leverage split queries so that EF will execute several queries against the database rather than attempting to join all related tables in one query.对于 EF Core,当你确实有一个合法的案例来急切加载大量实体,如嵌套子 collections,你应该利用拆分查询,以便 EF 将对数据库执行多个查询,而不是试图在一个查询中连接所有相关表。 The difference is that for the default eager load JOIN implementation where you have 1 top level entity with 15 columns and 10 related child entities with 10 columns, each with up to 2 grand child entities with 8 columns you generate a Cartesian product to pull back all combined columns across all combined rows which EF then iterates through to build the entity graph.不同之处在于,对于默认的急切加载 JOIN 实现,您有 1 个具有 15 列的顶级实体和 10 个具有 10 列的相关子实体,每个子实体最多有 2 个具有 8 列的大子实体,您生成一个笛卡尔积以拉回所有跨所有组合行的组合列,然后 EF 迭代这些列以构建实体图。 With split queries you still pull back all rows, but with separate queries so there is less data overall being sent.使用拆分查询,您仍然会拉回所有行,但使用单独的查询,因此总体上发送的数据较少。

The main reason you should avoid using eager loading for loading sets of data, especially things like "Get All" is that after transmitting and materializing all of those entities, by default the EF DbContext will be tracking each of those entities which means all further queries and such across that DbContext will involve comparing and inspecting the local tracked entities, slowing down future queries.您应该避免使用预先加载来加载数据集的主要原因,尤其是像“全部获取”这样的事情是在传输和具体化所有这些实体之后,默认情况下 EF DbContext 将跟踪这些实体中的每一个,这意味着所有进一步的查询这样,DbContext 将涉及比较和检查本地跟踪的实体,从而减慢未来的查询速度。

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

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