ASP.NET和EF非常慢

时间:2014-04-24 18:42:58

标签: c# asp.net entity-framework

通过使用EF,C#和ASP.NET 4 Web应用程序,我使用以下代码从数据库中检索数据并填充GridView:

using (AshModel am = this.conn.GetContext())
{
    IEnumerable<Article> articles = 
        (from a in am.Article.AsEnumerable()
         where (a.CultureName == calture || a.CultureName == 0)
             && a.IsApproved == status
             && a.IsPublished == status
         orderby a.AddedDate descending
         select a);

    IEnumerable<Profile> profiles = am.Profile.AsEnumerable()
        .Where(t => articles.Any(a => a.ProfileId == t.ProfileID));

    foreach (Article article in articles)
        article.UserProfile = profiles
            .Where(a => a.ProfileID == article.ProfileId)
            .FirstOrDefault();

    this.gvArticles.DataSource = articles.ToList();
    this.gvArticles.DataBind();
}

但它非常慢,响应大约需要2分钟,数据库中只有500条记录!我的错误是什么?我如何才能提高绩效? 谢谢。

3 个答案:

答案 0 :(得分:11)

你在某些地方正在做AsEnumerable()

执行此操作时,将从数据库中检索所有对象,然后对其进行过滤。

如果删除AsEnumerable(),则应该按预期工作。

答案 1 :(得分:1)

您的第二和第三部分可以用简单的Include表达式替换:

 var articles = 
    (from a in am.Article
     .Include(article=>article.UserProfile) //!!
     where (a.CultureName == calture || a.CultureName == 0)
         && a.IsApproved == status
         && a.IsPublished == status
     orderby a.AddedDate descending
     select a).ToList();

//no more DB calls in foreach loop

this.gvArticles.DataSource = articles.ToList();
this.gvArticles.DataBind();

因为在您的代码中,您首先选择文章,然后您找到至少在一篇文章中提到的个人资料(可以是整个数据集),然后您选择与您的文章匹配的个人资料...

答案 2 :(得分:-1)

这样的代码:

IEnumerable<Profile> profiles = am.Profile.AsEnumerable()
    .Where(t => articles.Any(a => a.ProfileId == t.ProfileID));

不会导致实际的集合/列表/要实例化的任何内容。这仅仅是描述如何检索和过滤对象的配方,但Where子句中的lambda表达式不在上面的行中执行。它只是一个表达式,用于定义如何在profiles集合中生成项目,但它不会生成它们。

只要请求任何项目,就会发生该代码的实际执行,在您的示例中,它会在.FirstOrDefault()调用时发生。但是,它在一个循环中。 实际上,您将在循环的每个步骤中重新查找DB。

由于一次加载一堆数据库记录要快得多,而不是单独加载它们,我建议将查询重写到Profile表,这样它就可以在尽可能少的事务中加载所需的全部内容。可能。对您而言,这意味着将代码段的第一行更改为:

IList<Article> articles = 
    (from a in am.Article
     where (a.CultureName == calture || a.CultureName == 0)
         && a.IsApproved == status
         && a.IsPublished == status
     orderby a.AddedDate descending
     select a).ToList();

IList<Profile> profiles = am.Profile.Where(t => articles.Any(a => a.ProfileId == t.ProfileID)).ToList();

总而言之,代码不一定在它发生的地方执行。您可能希望在C#中使用Google 延迟执行