2011-10-03 59 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; 
}