Как отследить дубликаты запросов Linq to SQL, определенных MiniProfiler? - PullRequest
3 голосов
/ 03 октября 2011

Я подключил MvcMiniProfiler к своему приложению, и он сообщает о дублирующих запросах.

Я установил точку останова в своем репозитории

    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

Ответы [ 2 ]

1 голос
/ 30 января 2012

У вас есть две возможности избежать SELECT n + 1 с LINQ to SQL:

1) Использовать DataLoadOptions - http://msdn.microsoft.com/en-us/library/system.data.linq.dataloadoptions.loadwith.aspx

DataLoadOptions позволяет вам указать для каждой сущности, какие связанные таблицы должны загружаться. В вашем случае для сущности Event вы можете указать LoadWith как для комментариев, так и для местоположений. Всякий раз, когда вы загружаете события, комментарии и места будут предварительно загружены.

DataLoadOptions - это свойство, которое вы можете установить в самом DataContext.

2) Используйте проекцию для извлечения всех данных, которые вам нужны в одном конкретном запросе , вместо того, чтобы полагаться на ленивую загрузку связанных объектов.

Вы наложили хранилище поверх вашего DataContext, так что это может быть не тот подход, который вы хотите использовать, но:

Вместо того, чтобы выбирать список Событий и затем использовать свойства этой сущности Комментарии и Местоположения, ваш запрос может возвращать именно то, что вам нужно в конкретном классе ViewModel. LINQ to SQL будет затем извлекать все в одном запросе SQL.

Я считаю, что это лучший подход, если вам абсолютно НЕ НУЖНО абстрагироваться от DataContext за интерфейсом хранилища. Даже если вы это сделаете, вы можете рассмотреть возможность возврата из репозитория. Посмотреть конкретные результаты, т.е.

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

с EventViewModel, равным

public class EventViewModel 
{
    Event Event;
    List<Location> Locations;
    List<Comment> Comments;
}
0 голосов
/ 26 января 2012

вы хотите, чтобы .Include("Locations") и .Include("Comments") в соответствующих запросах.Я полагаю, что это происходит до .Where(), но я не уверен в этом.

...