简体   繁体   English

当使用实体框架通过“包含”语句引用关联表时,将对其进行完全解析

[英]Associated tables being fully parsed when referred to with an 'Include' statement using Entity Framework

I'm having problems with Includes when pulling data out of the entity framework. 从实体框架中提取数据时,Includes出现问题。 I posted a very similar question yesterday here , which has the same sample I'm about to use. 我昨天在这里发布了一个非常类似的问题,该问题具有我将要使用的相同示例。 I'm using Entity Framework v4.0. 我正在使用Entity Framework v4.0。

I have the following simple model, a table containing list of Page Forms (~200). 我有以下简单模型,一个包含页面表单列表的表(〜200)。 Each form has one or more Fields (~4000 total), and each field has may have some Parameters (~16000 total). 每个表单都有一个或多个字段(总计约4000个),每个字段可能有一些参数(总计约16000个)。

实体模型

I use the following code to pull data out: 我使用以下代码提取数据:

EntityConnection myConnection = new EntityConnection("name=myModel");

if(conn.State != ConnectionState.Open) {
    conn.Open();
}
ObjectContext context = new ObjectContext("name=myModel");
context.ContextOptions.LazyLoadingEnabled = false;

ObjectQuery<PageForm> myObjectSet = context.CreateObjectSet<PageForm>()
                                           .Include("FormFields.FormFieldParameters");

IQueryable<PageForm> myFilteredObjectSet = myObjectSet.Where(c => c.FormID == 1);

List<PageForm> myReturnValue = myFilteredObjectSet.toList();

Which generates the following sql query 哪个生成以下sql查询

SELECT 
[Project1].[FormID] AS [FormID], 
[Project1].[FormName] AS [FormName], 
[Project1].[C2] AS [C1], 
[Project1].[FormID1] AS [FormID1], 
[Project1].[FieldID] AS [FieldID], 
[Project1].[FieldName] AS [FieldName], 
[Project1].[C1] AS [C2], 
[Project1].[FieldParamID] AS [FieldParamID], 
[Project1].[Value] AS [Value], 
[Project1].[FieldID1] AS [FieldID1]
FROM ( 
    SELECT 
    [Extent1].[FormID] AS [FormID], 
    [Extent1].[FormName] AS [FormName], 
    [Join1].[FieldID] AS [FieldID], 
    [Join1].[FieldName] AS [FieldName], 
    [Join1].[FormID] AS [FormID1], 
    [Join1].[FieldParamID] AS [FieldParamID], 
    [Join1].[Value] AS [Value], 
    [Join1].[FieldID1] AS [FieldID1], 
    CASE WHEN ([Join1].[FieldID] IS NULL) THEN CAST(NULL AS int) WHEN ([Join1].[FieldParamID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1], 
    CASE WHEN ([Join1].[FieldID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
    FROM  [dbo].[PageForm] AS [Extent1]
    LEFT OUTER JOIN (
        SELECT 
        [Extent2].[FieldID] AS [FieldID], 
        [Extent2].[FieldName] AS [FieldName], 
        [Extent2].[FormID] AS [FormID], 
        [Extent3].[FieldParamID] AS [FieldParamID], 
        [Extent3].[Value] AS [Value], 
        [Extent3].[FieldID] AS [FieldID1]
        FROM  [dbo].[FormField] AS [Extent2]
        LEFT OUTER JOIN [dbo].[FormFieldParameter] AS [Extent3] ON [Extent2].[FieldID] = [Extent3].[FieldID] 
    ) AS [Join1] ON [Extent1].[FormID] = [Join1].[FormID]
    WHERE 1 = [Extent1].[FormID]
) AS [Project1]
ORDER BY [Project1].[FormID] ASC, [Project1].[C2] ASC, [Project1].[FieldID] ASC, [Project1].[C1] ASC

Now I'm interested in this part of the query: 现在,我对查询的这一部分感兴趣:

LEFT OUTER JOIN (
    SELECT 
    /**/
    FROM  [dbo].[FormField] AS [Extent2]
    LEFT OUTER JOIN [dbo].[FormFieldParameter] AS [Extent3] ON [Extent2].[FieldID] = [Extent3].[FieldID] 
) AS [Join1] ON [Extent1].[FormID] = [Join1].[FormID]

This seems to query the entire FormField and FormFieldParameter tables, with no filtering applied. 这似乎查询整个FormField和FormFieldParameter表,没有应用过滤。 So, what I think is happening, is that using .Include("FormField.FormFieldParameter") is akin to saying - "And return all data from these tables in the resulting query". 因此,我认为正在发生的事情是,使用.Include("FormField.FormFieldParameter")类似于说-“并在结果查询中返回这些表中的所有数据”。 What I really want is "Return only the data from these tables which relates to the filtered PageForm table". 我真正想要的是“从这些表中,其涉及过滤PageForm表仅仅返回数据”。

Is there a way to do this? 有没有办法做到这一点? Sorry if this question sounds too simple, or similar to my previous question, but I'm really having trouble getting my head around the internals of Entity Framework. 抱歉,这个问题听起来太简单了,或者与我之前的问题类似,但是我很难理解Entity Framework的内部结构。

EDIT 1: 编辑1:

If I change the above sample to the following which includes a where clause, then the query is orders of magnitude faster (roughly 10x faster). 如果将上面的示例更改为以下包含where子句的示例,则查询的速度将提高几个数量级(大约快10倍)。

LEFT OUTER JOIN (
    SELECT 
    /**/
    FROM  [dbo].[FormField] AS [Extent2]
    LEFT OUTER JOIN [dbo].[FormFieldParameter] AS [Extent3] ON [Extent2].[FieldID] = [Extent3].[FieldID] 
    WHERE 1 = [Extent2].[FormID]
) AS [Join1] ON [Extent1].[FormID] = [Join1].[FormID]

EDIT 2: 编辑2:

Some more information. 一些更多的信息。 I've figured out that If i add some funky filtering to the initial query, I can force a much more efficient query to be ran. 我已经发现,如果在初始查询中添加一些时髦的过滤条件,则可以强制执行效率更高的查询。

IQueryable<PageForm> myFilteredObjectSet = myObjectSet
                                          .Where(c => c.FormID == 1)
                                          .Where(a => a.FormFields
                                                       .Where(c => c.FormFieldParameters
                                                                    .Any(d => d.FieldID == c.FieldID))
                                                       .Any(b => b.FormID == 1)
                                           );

This causes the query to filter correctly, and runs much faster. 这将导致查询正确过滤,并且运行速度更快。 However, I'm certain this isn't the best way go about this, as the nested Where/Any statements very quickly become a nightmare to deal with when you have more than a handful of Includes. 但是,我敢肯定这不是解决问题的最佳方法,因为当您拥有多个Includes时,嵌套的Where / Any语句很快就会成为噩梦。 There must be a better way? 一定会有更好的办法?

The filtering is applied - your query contains WHERE 1 = [Extent1].[FormID] . 应用过滤-您的查询包含WHERE 1 = [Extent1].[FormID] It really loads only date you have requested. 它实际上仅加载您请求的日期。 The query engine in the database will evaluate your query correctly and it will use some optimization techniques to filter records efficiently. 数据库中的查询引擎将正确评估您的查询,并将使用一些优化技术来有效地过滤记录。

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

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