首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在枚举关联时提高糟糕的EF4性能?

如何在枚举关联时提高糟糕的EF4性能?
EN

Stack Overflow用户
提问于 2012-07-13 07:51:46
回答 2查看 95关注 0票数 2

我正在使用Entity Framework4(数据库优先)开发电影数据库应用程序,将大约8200行加载到列表中需要30秒。这里涉及三个表,当我使用.Include()时,性能下降得更厉害--加载8,200行几乎需要3分钟。这是痛苦的。考虑到我同时学习了很多技术,我希望有一个简单的解决方案。以下是详细信息:

表1-视频

这是一个有31列的大表,大约有7,800行视频。它使用Guid作为其主键。

表2- ActorsVideos (连接表)

此表有两列:(1) VideoID列和(2) ActorID列。这两列都是Guid,并且分别是Video和Actor表的外键。此表使用复合主键,其中两列都充当主键。EF4不会对此表进行建模;但是,它会创建一个导航属性。此表允许用户将任意数量的演员分配给一部电影。

表3-执行元

有16列,大约400行。同样,主键是一个Guid。

在代码中,我读取了Videos表中的大约10列,然后从关联的Actors表中读取了列。

C#代码如下所示:

代码语言:javascript
复制
var videos = context.Videos
foreach (var video in videos)
{
    // retrieve 10 or so properties from 'video'

    if (video.Actors.Count > 0)
    {
        foreach (var actor in video.Actors)
        {
            // retrieve some properties on the actor
        }
    }
}

我试着在context.Videos后面添加.Include(“演员”),如上所述,性能从糟糕到可怕。

我查看了使用Include生成的SQL,给定video表中的列数,它大约有2K的文本。

我必须使用Master/Detail模式拆分视频表吗?我的下一步是缓存参与者表,并完全避免使用导航/关联属性。有没有其他建议可以让这一切变得更快?在我看来,它应该在5-6秒内运行。

编辑:数据库为SQL Server CE 3.5。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-13 09:06:59

您请求Entity Framework加载一个视频及其所有参与者,然后在应用程序代码中进行过滤。通常,您提取的数据比需要的多得多。我会让SQL Server (或您正在使用的任何数据库)为您预筛选:

代码语言:javascript
复制
var videos = context.Videos;
var results = from video in videos
              where video.Actors.count > 10
              group video.Actors by video.VideoID into grouping
          select new
          {
              video.VideoID,
              video.Actors
          };

foreach (var group in results)
{
    foreach (var actor in group.Actors)
    {
        // do stuff
    }
}

加载~8200行,以及它们在videos表中的相关行应该是非常快的。在我的工作中,我做了一些开发工作,我必须处理一个具有5个表连接的70+百万行测试数据表。大概半分钟就到了。

但是,它运行得比您所做的要快得多的原因是因为我在SQL Server中进行了过滤。使用EF的等效“过程”程序需要几分钟时间,因为我是在从数据库中提取行之后进行过滤的。

可以这样想:您不仅请求数据库中的每一行,而且还拉入了您甚至不需要多次使用的数据。

票数 3
EN

Stack Overflow用户

发布于 2012-07-13 08:56:12

尝试使用eager loading

代码语言:javascript
复制
var videos = context.Videos.Include(v=>v.Actors);
foreach (var video in videos)
{
    foreach (var actor in video.Actors)
    {
    }
}

注意:注意,查询使用延迟执行,这意味着多次迭代也会多次执行查询。如果要进行多次迭代,请在迭代之前使用.AsEnumerable()并将其分配到本地。此外,分析数据库以查看正在执行哪些查询将有助于确定您还需要获取哪些内容。您可能会强制EF加载不需要的实体。如果是这样,那么您的查询应该只投影(通过使用Select(x=> new {...stuff you need... }))必要的数据。

编辑:根据Microsoft的说法,Include()不能与投影组合,因此在这种情况下,您需要以不同的方式编写查询。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11462356

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档