2009-04-10 6 views
1

ich zwei Tabellen haben, die wie folgt aussehen:LinqToSql - Mehrere Unterabfragen erstellt viele Roundtrips

alt text http://www.brettrobichaud.com/images/linq.png

Ich versuche Abfrage zu generieren, die für jede Periode von ApplianceStatisticsLog zwei spezifischen StatisticsNames enthält. Unten ist die Linq-Abfrage, die ich mir ausgedacht habe. Es funktioniert, aber generiert eine einzelne Abfrage für die erste Unterauswahl, dann eine zusätzliche Abfrage für jeden Datensatz für die zweite Unterauswahl. Aua, die DB-Roundtrips bringen mich um.

Wie kann ich dies überarbeiten, um eine einzige SQL-Abfrage auszuquetschen?

from l in ApplianceStatisticsLogs 
where l.ApplianceServerId > 1 
orderby l.PeriodEndUtc ascending 
select new 
{ 
Time = l.PeriodEndUtc, 
Stat1 = from s in ApplianceStatistics 
     where s.ApplianceStatisticsLogId == l.ApplianceStatisticsLogId 
      && s.ApplianceStatisticNameId == 2 
     select s.Value, 
Stat2 = from s in ApplianceStatistics 
     where s.ApplianceStatisticsLogId == l.ApplianceStatisticsLogId 
      && s.ApplianceStatisticNameId == 3 
     select s.Value 
} 
+0

@BrettRobi überprüfen Sie meine Antwort, wenn Sie eine Chance bekommen, sollte es für Ihr Szenario funktionieren. – eglasius

Antwort

0

Freddy war auf dem richtigen Weg und fast hatte. Die Lösung war die Verwendung von First() für jede Unterabfrage. Wie in:

from l in ApplianceStatisticsLogs 
where l.ApplianceServerId > 1 
orderby l.PeriodEndUtc ascending 
select new 
{ 
    Time = l.PeriodEndUtc, 
    Stat1 = (from s in ApplianceStatistic 
      where s.ApplianceStatisticsLogId == l.ApplianceStatisticsLogId 
       && s.ApplianceStatisticNameId == 2 
      select s.Value).First(), 
    Stat2 = (from s in ApplianceStatistics 
      where s.ApplianceStatisticsLogId == l.ApplianceStatisticsLogId 
       && s.ApplianceStatisticNameId == 3 
      select s.Value).First() 
} 

hatte ich versäumt zu erwähnen, dass nur ein Datensatz in den Unterabfragen entsprechen sollte. Danke für die Hilfe Freddy!

1

Update (basierend auf Beziehung):

select new 
{ 
Time = l.PeriodEndUtc, 
Stat1 = (from s in l.ApplianceStatistics 
     where s.ApplianceStatisticNameId == 2 
     select s.Value 
     ).ToList(), 
Stat2 = (from s in l.ApplianceStatistics 
     where s.ApplianceStatisticNameId == 3 
     select s.Value 
     ).ToList() 
} 

Versuchen:

select new 
{ 
Time = l.PeriodEndUtc, 
Stat1 = (from s in ApplianceStatistics 
       where s.ApplianceStatisticsLogId == l.ApplianceStatisticsLogId 
        && s.ApplianceStatisticNameId == 2 
       select s.Value 
     ).ToList(), 
Stat2 = (from s in ApplianceStatistics 
       where s.ApplianceStatisticsLogId == l.ApplianceStatisticsLogId 
        && s.ApplianceStatisticNameId == 3 
       select s.Value 
     ).ToList() 
} 
+0

Fast. Die Verwendung von ToList() in beiden Unterabfragen erzeugte immer noch einen Roundtrip für jeden Datensatz im Hauptabfrageergebnis. Die Lösung verwendet stattdessen First(). Ich hätte erwähnen sollen, dass nur ein Datensatz übereinstimmen sollte. – BrettRobi

+0

@ Brett bist du sicher? Wo verwendest du einen anonymen Typ bei der Rückkehr wie im Beispiel? Ich habe nur ein paar Tests gemacht, und ich kann es eigentlich nicht dazu bringen, mehrere Runden zu machen (auch ohne ToList - also stimme ich zu, dass prob keine Wirkung hat) ... vielleicht etwas mit dem Typ, dem du es zugewiesen hast? – eglasius

+0

Ich hatte eigentlich keinen störenden Typ. Ich habe diese Änderung vorgenommen, um meine Stichprobe zu vereinfachen. Denkst du, dass es einen Unterschied machte, wenn man es als konkreten Typ vorstellte? Ich hätte nie gedacht, dass das im SQL etwas bewirken könnte. – BrettRobi