2011-10-03 63 views
3

我已將MvcMiniProfiler連接到我的應用程序,它報告重複查詢。如何追蹤由MiniProfiler識別的重複Linq到SQL查詢?

我設置一個斷點在我的倉庫

Public Function Read() As System.Linq.IQueryable(Of [Event]) Implements IEventRepository.Read 
     Dim events = (From e In dc.Events 
         Select e) 
     Return events.AsQueryable ''# BREAKPOINT HERE 
    End Function 

,我已經打了有問題的網頁。

我的代碼,通過我的服務層打Read()功能兩次(這是由設計,因爲我無法弄清楚如何降低話費)

 Dim eventcount = EventService.GetHotEventCount() ''# First Hit 
     Dim eventlist = EventService.GetHotEvents((page - 1) * 5) ''# Second Hit 
     Dim model As EventsIndexViewModel = New EventsIndexViewModel(eventlist, page, eventcount) 

     Return View("Index", model) 

EventService做一個簡單的查詢反對IQueryable的Read

Public Function GetHotEvents(ByVal skip As Integer) As List(Of Domain.Event) Implements IEventService.GetHotEvents 

     Return _EventRepository.Read() _ 
      .Where(Function(e) e.EventDate >= Date.Today AndAlso 
           e.Region.Name = RegionName) _ 
      .OrderByDescending(Function(e) (((e.TotalVotes) * 2) + e.Comments.Count)) _ 
      .ThenBy(Function(e) e.EventDate) _ 
      .Skip(skip) _ 
      .Take(5) _ 
      .ToList() 
    End Function 

不幸的是我無法弄清楚,爲什麼MiniProfiler是說有8級重複的查詢(13總共)。

修訂
所以看起來好像山姆說,我不是預加載我的查詢中我的關係。

如何適當地預加載Linq to SQL中的關係?任何人都可以借用任何建議嗎?

編輯
這裏是正在創建的ViewModel。

Public Class EventsIndexViewModel 
    Public Property Events As List(Of Domain.ViewModels.EventPreviewViewModel) 
    Public Property PageNumber As Integer 
    Public Property TotalEvents As Integer 
    Public Property MapEventsList As List(Of Domain.Pocos.MapPin) 
    Public Property JsonMapEventsList As String 

    Sub New() 
    End Sub 

    Sub New(ByVal eventlist As List(Of Domain.Event), ByVal page As Integer, ByVal eventcount As Integer) 

     _PageNumber = page 
     __TotalEvents = eventcount 

     Dim mel As New List(Of MapPin) 
     _Events = New List(Of Domain.ViewModels.EventPreviewViewModel) 
     For Each e In eventlist 
      _Events.Add(New Domain.ViewModels.EventPreviewViewModel(e)) 
      mel.Add(New MapPin(e.Location.Latitude, e.Location.Longitude, e.Title, e.Location.Name, e.Location.Address)) 
     Next 

     _MapEventsList = mel 
     _JsonMapEventsList = (New JavaScriptSerializer()).Serialize(mel) 

    End Sub 
End Class 

編輯 - 添加截圖

miniProfiler Screen Shot

+0

迷你探查顯示了一個堆棧跟蹤的各種處決,照顧到包括查詢時間線的屏幕快照? –

+0

我已添加查詢...我無法找到堆棧跟蹤 –

+0

這是經典的n + 1東西,您的查詢中的關係未被預加載,特別是.Comments和.Locations –

回答

0

你會想在各自的查詢.Include("Locations").Include("Comments")。我相信它在.Where()之前,但我對此沒有正面評價。

+0

他正在使用Linq to SQL。包括是爲實體框架 – TheNextman

+0

哎喲,那就不理我了。 :) – Aaron

1

你基本上有兩種選擇,避免選擇N + 1的LINQ to SQL:

1)使用DataLoadOptions - http://msdn.microsoft.com/en-us/library/system.data.linq.dataloadoptions.loadwith.aspx

DataLoadOptions允許您爲每個實體指定正是相關的表應該是渴望-loaded。在你的情況下,對於實體事件,你可以爲註釋和位置指定LoadWith。每當你加載事件,評論和地點將被預先加載。

DataLoadOptions是您可以在DataContext本身上設置的屬性。

2)使用投影在一個特定查詢中獲取所需的所有數據,而不是依賴延遲加載相關實體。

你強加給你的DataContext頂部的存儲庫,所以這可能不是你想要採取的方法,但是:

而是選擇事件的列表,然後使用該實體的屬性評論和地點,您可以讓您的查詢完全返回您在特定ViewModel類中需要的內容。然後,LINQ to SQL將在單個SQL查詢中獲取所有內容。

我認爲這是最好的方法,如果你不是絕對需要在存儲庫接口後面抽象出DataContext。即使你做的,你可以考慮用EventViewModel是

具有存儲庫返回查看具體的結果,即

dc.Events 
    .Where(something) 
    .Skip(something) 
    .Select(event => new EventViewModel 
     { 
      Event = event 
      Locations = event.Locations, 
      Comments = event.Comments 
     } 
    ); 

public class EventViewModel 
{ 
    Event Event; 
    List<Location> Locations; 
    List<Comment> Comments; 
}