3

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()私のコードは、サービス層を介して関数を 2 回ヒットします(呼び出しを減らす方法がわからないため、これは設計によるものです)

        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)

EventServiceIQueryable に対して単純なクエリを実行します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) があると言っている理由がわかりません。

改訂
されたので、Sam は、クエリ内で関係をプリロードしていないと述べているように見えます。

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 スクリーンショット

4

2 に答える 2

1

LINQ to SQL で SELECT n+1 を回避するには、基本的に 2 つのオプションがあります。

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

DataLoadOptions を使用すると、エンティティごとに、関連するテーブルをeager-loadする必要があることを正確に指定できます。あなたの場合、エンティティ イベントの場合、コメントと場所の両方に LoadWith を指定できます。イベントをロードするたびに、コメントと場所がプリロードされます。

DataLoadOptions は、DataContext 自体に設定できるプロパティです。

2) プロジェクションを使用して、関連するエンティティの遅延読み込みに頼るのではなく、1 つの特定のクエリで必要なすべてのデータをフェッチします。

DataContext の上にリポジトリを課したため、これは取りたいアプローチではないかもしれませんが、次のようになります。

イベントのリストを選択してから、このエンティティのプロパティであるコメントと場所を使用する代わりに、特定の ViewModel クラスで必要なものをクエリで正確に返すことができます。LINQ to SQL は、1 つの SQL クエリですべてをフェッチします。

リポジトリ インターフェイスの背後にある DataContext を抽象化する必要がまったくない場合は、これが最善の方法だと思います。そうした場合でも、リポジトリが View 固有の結果を返すようにすることを検討できます。つまり、

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;
}
于 2012-01-30T11:29:52.690 に答える
0

それぞれのクエリで必要になります.Include("Locations").Include("Comments")の前に行くと信じていますが.Where()、それについては前向きではありません。

于 2012-01-26T18:29:12.340 に答える