Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当使用';包括';使用实体框架的语句_C#_Entity Framework_Entity Framework 4 - Fatal编程技术网

C# 当使用';包括';使用实体框架的语句

C# 当使用';包括';使用实体框架的语句,c#,entity-framework,entity-framework-4,C#,Entity Framework,Entity Framework 4,我在从实体框架中提取数据时遇到了包含问题。我昨天发布了一个非常类似的问题,这个问题与我将要使用的示例相同。我使用的是实体框架v4.0 我有以下简单的模型,一个包含页面表单列表的表(~200)。每个表单有一个或多个字段(总计约4000个),每个字段可能有一些参数(总计约16000个) 我使用以下代码提取数据: EntityConnection myConnection = new EntityConnection("name=myModel"); if(conn.State != Connec

我在从实体框架中提取数据时遇到了包含问题。我昨天发布了一个非常类似的问题,这个问题与我将要使用的示例相同。我使用的是实体框架v4.0

我有以下简单的模型,一个包含页面表单列表的表(~200)。每个表单有一个或多个字段(总计约4000个),每个字段可能有一些参数(总计约16000个)

我使用以下代码提取数据:

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();
现在我对查询的这一部分感兴趣:

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]
这似乎查询了整个FormField和FormFieldParameter表,没有应用任何筛选。因此,我认为正在发生的是,使用
.Include(“FormField.FormFieldParameter”)
类似于说“并在结果查询中返回这些表中的所有数据”。我真正想要的是“只返回这些表中与筛选的PageForm表相关的数据”

有办法做到这一点吗?很抱歉,如果这个问题听起来太简单,或者与我之前的问题类似,但是我真的很难理解实体框架的内部结构

编辑1:

如果我将上面的示例更改为包含where子句的以下示例,那么查询速度会快几个数量级(大约快10倍)

编辑2:

更多信息。我发现,如果我在初始查询中添加一些时髦的过滤,我可以强制运行一个更高效的查询

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)
                                           );
IQueryable myFilteredObjectSet=myObjectSet
.其中(c=>c.FormID==1)
.其中(a=>a.FormFields
.其中(c=>c.FormFieldParameters
.Any(d=>d.FieldID==c.FieldID))
.Any(b=>b.FormID==1)
);

这会使查询正确过滤,并且运行得更快。然而,我确信这不是最好的解决方法,因为嵌套的Where/Any语句很快就会成为一场噩梦,当你有超过一把include时,它就成了一场噩梦。一定有更好的方法吗?

已应用筛选-您的查询包含
其中1=[Extent1].[FormID]
。它实际上只加载您请求的日期。数据库中的查询引擎将正确评估您的查询,并将使用一些优化技术有效地筛选记录。

很抱歉,但我确信这是不正确的。如果手动更新查询以包含内部where子句,则查询运行速度会快得多。我将更新我的问题来说明这一点。好吧,现在它变成了完全不同的问题,因为您以前的问题是关于返回错误的数据,而新的问题是关于不同的性能。是的,EF查询的性能可能要差得多,但唯一的解决办法是不使用Linq和EF并编写您自己的SQL查询。我想您误解了-在这两种情况下,我得到的数据与预期完全一致。问题是生成的查询是从整个“FormField”表中选择的,而该查询只应从
FormID==1的表中选择。我知道在使用EF时会有开销,但这是一个巨大的性能损失,我确信我一定是做错了什么。请参阅我的问题,了解一个解决方法,它是有效的,但与sin一样丑陋。我相信一定有更好的方法。不幸的是,你没有做错任何事。您可以尝试使用.NET4.5-可能会有一些性能改进,将其作为错误报告给,将其作为改进请求报告给,或在上打开设计讨论。您还可以从codeplex下载EF源代码,并尝试自己修复它。这种解决方法不会急于加载您的关系。即使您添加了Include,它仍然不会过滤Include,因为它似乎急切地为我加载一切正常,并且我运行的sql探查器只显示了一个正在进行的调用—这是在我调用可查询对象上的
.ToList()
时。
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]
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)
                                           );