ASP.NET和EF非常非常慢

本文关键字:非常 EF NET ASP | 更新日期: 2023-09-27 18:00:12

通过使用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条记录!我的错误是什么?如何提高绩效?谢谢

ASP.NET和EF非常非常慢

您在某些部分执行AsEnumerable()

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

如果删除了这些AsEnumerable(),它应该可以正常工作。

您的第二部分和第三部分可以替换为简单的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();

因为在你的代码中,你首先选择文章,然后你会发现至少在一篇文章中提到的配置文件(可以是一整套数据),然后你选择与你的文章匹配的配置文件。。。

这样的代码:

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

不会导致实际的集合/列表/任何东西被实例化。这只是一个描述如何检索和筛选对象的配方,但Where子句中的lambda表达式并没有在上面的行中执行。它只是一个定义如何在profiles集合中生成项的表达式,但并不生成它们。

该代码的实际执行发生在请求任何项目时,在您的示例中,它发生在.FirstOrDefault()调用上。然而,它是在一个循环中。实际上,循环的每一步都需要DB。

由于一次加载一堆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#中搜索延迟执行