2009-05-27 4 views
2

Dieses Szenario kommt oft, jetzt, wo ich LinkToSql und die Klassen verwenden, die es erstellt.LinqToSql - übermäßige Anfragen an die Datenbank zu vermeiden

Klassisches Szenario - zwei Tabellen:

Mitglied
ID
Namen
...

Mitgliedschaft
ID
MemberID (Fremdschlüssel)
Start (Datumzeit)
Verfall (DatumZeit)
...

Eine aktive Mitgliedschaft wäre eine, die jetzt zwischen Start und Ablauf ist.

Um herauszufinden, ob ein Benutzer eine aktive Mitgliedschaft hat, wie ich diese partielle Klasse erstellt haben, auf dem LinkToSql generierten Member-Klasse zu erweitern:

Partial Public Class Member 
    Public ReadOnly Property HasActiveMembership() As Boolean 
     Get 
      Dim activeMembershipCount As Integer = (From m In Me.Memberships _ 
           Where m.MemberId = Me.MemberId _ 
           And m.StartDate < Now And m.ExpirationDate > Now() _ 
           Select m).Count 

      If activeMembershipCount > 0 Then Return True Else Return False 

     End Get 
    End Property 
End Class 

Dies funktioniert gut für ein Mitglied, aber wenn ich will um 700 Mitglieder aufzulisten und wenn sie eine aktive Mitgliedschaft haben oder nicht, führt sie mehr als 700 Aufrufe an die Datenbank durch.

Wie soll ich mein Modell/meine Klassen ändern?

Ich könnte eine Abfrage nur für Listen erstellen, wo machen Sie die ganze Sache in eine Abfrage, die ziemlich einfach ist, aber ich möchte das vermeiden, wenn ich könnte.

Antwort

2

Sie haben ein paar Optionen; Zum Beispiel könnten Sie DataLoadOptions.LoadWith oder DataLoadOptions.AssociateWith verwenden, um die Daten eifrig zu holen - der optimale Ansatz hängt jedoch davon ab, wie Sie ihn verwenden.

Zum Beispiel könnten Sie eine Abfrage "Benutzer mit aktiver Mitgliedschaft" schreiben (entweder in LINQ mit Any oder mit einem SPROC/UDF). Das wäre dann eine Rundreise, ist aber wohl weniger objektzentriert (und eher query-centric). Was könnte gut sein ...

0

Es sieht so aus, als ob Sie bereits eine Assoziation definiert haben, vielleicht aufgrund einer FK-Beziehung zwischen den Tabellen. In diesem Fall können Sie einfach Ihre Mitgliedschaftsabfrage mithilfe einer where-Klausel erweitern, indem Sie den bereits in der Klasse definierten Entitätsverweis verwenden.

C# Beispiel:

var query = db.Members.Where(m => m.Memberships 
            .Any(ms => ms.StartDate > now 
               && ms.ExpirationDate < now)); 
+0

Was ich suche ist eine Möglichkeit, alle Mitglieder zu zeigen - und ein wahr/falsch, wenn sie tatsächlich eine aktive Mitgliedschaft haben. Nicht nur die Mitglieder mit einer tatsächlich aktiven Mitgliedschaft. :) – Kjensen

+0

Betrachte @ Marc's Antwort in Bezug auf die DataLoadOptions. Wenn die Daten nicht lazy geladen werden, wird Ihre Abfrage gegen Mitgliedschaften nicht gegen die Datenbank zurückgehen - es wird LinqToObjects sein. Sie sollten wahrscheinlich Any() verwenden, anstatt auch die Anzahl zu berechnen. Ich würde erwarten, dass es in LinqToObjects einen Kurzschluss geben wird, nachdem der erste gefunden wurde. Count müsste sie alle untersuchen. Wahrscheinlich ein kleiner Leistungsvorteil, aber es ist die richtige Methode zu verwenden. – tvanfosson

+0

Besser als Kurzschluss; in vielen Fällen wird EXISTS/COUNT/TOP 1 usw. verwendet (ich kann mich nicht erinnern, welche), anstatt sie alle tatsächlich zu holen –

Verwandte Themen