2013-04-22 50 views
5

我遇到了EF查詢的一些性能問題。如何以最有效的方式獲得懶惰列表的數量?

我們基本上是這樣的:

public class Article 
{ 
    public int ID { get; set; } 
    public virtual List<Visit> Visits { get; set; } 
} 
public class Visit 
{ 
    public int? ArticleID { get; set; } 
    public DateTime Date { get; set; } 
} 

現在,我想這樣做:

Article a = ...; 
vm.Count = a.Visits.Count; 

的問題是,從我所知,這首先使整個列表被取出,然後計算它。在循環中執行此操作時會產生性能問題。

我認爲這是由於對象太「具體」,所以我試圖將Visits.Count調用盡可能地移回存儲庫中(這樣我們就可以直接使用DbContext )。這沒有幫助。

有什麼建議嗎?

+0

你可以在文章中添加一個'GetVisitsCount'? - 取決於你計劃使用它多少,如果它只有幾次然後它不會是一個性能問題無論如何,所以我認爲它相當多 – Sayse 2013-04-22 10:18:14

回答

0

假設你的數據上下文有一個訪問屬性:

public class MyDbContext: DbContext 
{ 
    public IDbSet<Article> Articles { get; set; } 
    public IDbSet<Visit> Visits { get; set; } 
} 

,你可以這樣做:

using (var ctx = new MyDbContext()) 
{ 
    var count = ctx.Visits.Where(x => x.ArticleID == 123).Count(); 
} 

此外,如果訪問收集處理文章時不總是需要的,你可以聲明它爲IEnumerable<T>

public class Article 
{ 
    public int ID { get; set; } 
    public virtual IEnumerable<Visit> Visits { get; set; } 
} 

然後依靠延遲加載。

+0

這似乎是迄今爲止最好的選擇,並且接近迄今爲止我所做的。我做了類似的事情,但在訪問和文章之間加入了一些聯繫。 – NiklasJ 2013-04-22 12:10:55

+0

我不知道我是否應該將此標記爲解決方案或我的標記。這更好,但不是我做得如何。 IEnumerable「詭計」似乎並不奏效,但我不得不使用ICollection。 – NiklasJ 2013-04-22 16:27:42

0

我認爲性能問題可能是在延遲加載。 (但需要看到更多的代碼)。

在您從dbcontext檢索文章的那一刻嘗試使用include(a => a.Visits)。

關於EF性能更inforamtion:http://www.asp.net/web-forms/tutorials/continuing-with-ef/maximizing-performance-with-the-entity-framework-in-an-asp-net-web-application

+0

我試過這個,但這並沒有太大的幫助。我仍然認爲這個龐大名單的「具體化」是問題,而這只是稍微推動了評估。 – NiklasJ 2013-04-22 12:07:13

0

最後我做了另一種方式。

我發現,這是在不同的方式打了個遍,並且由於域模型的其餘部分被設置方式,我做了一個黑客攻擊的一位:

在我VisitRepository我創建了一個新函數GetArticleIDsWithVisit(),它通過db.SqlQuery直接調用sql,返回一個Dictionary。該字典被緩存並用於需要訪問計數的所有地方。

不是很漂亮,但我已經將它包裝在存儲庫中,所以我認爲沒關係。