通过使用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条记录!我的错误是什么?我如何才能提高绩效? 谢谢。
答案 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 延迟执行。