Frage

Wie können verschachtelte Listen verzögert geladen werden, ohne die Abfrage tatsächlich auszuführen?Nehmen wir an, ich habe anhand eines sehr einfachen Beispiels Folgendes:

class CityBlock {
     IList<Building> BuildingsOnBlock;
     Person BlockOwner;
}

class Building {
     IList<Floor> FloorsInBuilding;
}

class Floor {
     IList<Cubicle> EmployeeCubicles;
}

Class Cubicle {
     System.Guid CubicleID;
     Person CubicleOccupant;
}

Und dann habe ich in meiner Repository-Ebene die folgende Methode:

GetCityBlocks()

Und dann habe ich in der Service-Ebene GetCityBlocksByOwner, wo ich eine Erweiterungsmethode verwende, um die Stadtblöcke abzurufen, die einer bestimmten Person gehören, sagen wir, wir wollen nur Guidos Blöcke:

GetCityBlocks().ForOwner("Guido")

Wenn wir .ToList() im Repository ausführen, werden die Abfragen ausgeführt – das wäre lächerlich, da wir nicht wissen, welche Blöcke wir auf dieser Ebene erhalten.Die Frage ist also: Wie machen wir das effizient?

Gehen wir davon aus, dass es 50.000 Blockbesitzer und etwa 1.000.000 Stadtblöcke gibt, dann ist es keine Option, sie alle zu laden.Die Verwendung von IQueryables wird aufgrund der Verschachtelung nicht funktionieren (ohne extremes Hacking, zumindest soweit ich weiß).Wenn ich außerdem versuche, so etwas wie Rob Conerys LazyList zu verwenden, dann haben wir im Wesentlichen ein Leck von unserer DAL in unsere Domänenmodelle, was in Zukunft sehr, sehr schlimm sein könnte.

Wie mache ich das also richtig?

  • Ist es eine Frage der Bestimmung des richtigen Kontextes?Wenn ja, würden wir dies in der Repository -Ebene oder in der Serviceschicht tun?
  • Verschmelde ich die Serviceschicht und meine Repository -Ebene halb zusammen, um sehr spezifische Servicemethoden zu erhalten?
  • Oder übersehe ich etwas völlig?(immer noch relativ neu im LINQ2SQL -Ding, das sowieso ausgestiegen ist ...)

Bearbeiten:Im Repository-Muster führen wir derzeit eine Zuordnung zu unseren Domänenobjekten durch, das würde also etwa so aussehen:

public IQueryable<CityBlock> GetCityBlocks(){
    var results = from o in db.city_blocks
                  let buildings = GetBuildingsOnBlock(o.block_id)
                  select new CityBlock {
                      BuildingsOnBlock = buildings,
                      BlockOwner = o.block_owner
                  };
    return results;
}

Damit dies funktioniert, müssten wir dafür sorgen, dass die Gebäude ein .ToList() erhalten, es sei denn, wir machen das tatsächliche Feld im CityBlock-Objekt zu einem IQueryable – was nicht richtig erscheint, weil es den Anschein hat, als wäre es zu viel Leistung Wird jedem gewährt, der auf das Feld CityBlock.BuildingsOnBlock zugreift.Ist diese Zuordnung zu unseren Domänenobjekten etwas, das wir vielleicht auf der Serviceebene vornehmen sollten?

War es hilfreich?

Lösung

Sie tun dies, indem Sie IQueryables anstelle von ILists zurückgeben.

ToList() bewirkt, dass die Abfragen sofort ausgeführt werden, da eine Konvertierung von IQueryable nach IList durchgeführt werden muss.

Solange Sie IQueryables zurückgeben, sollte das verzögerte Laden die Ausführung verzögern, bis die Daten tatsächlich benötigt werden, d. h.wenn ToList() aufgerufen wird.

Ich kann im Moment keine Referenz finden, aber ich verstehe, dass linq to sql auf diese Weise die Möglichkeit hat, das an den Server gesendete SQL zu optimieren.Mit anderen Worten: Letztendlich werden diese Datensätze gelesen:

GetCityBlocks().ForOwner("Guido")

statt dieser Aufzeichnungen:

GetCityBlocks()

Andere Tipps

Sie könnten beim Zuordnen Ihrer Domänenobjekte einen anderen Ansatz ausprobieren, damit es funktioniert.Das Problem besteht darin, dass Sie, egal was Sie tun (es sei denn, Sie ändern Ihre Listen in Ihren Domänenobjekten in IQueryables), während der Zuordnung am Ende mit ToList()ing enden.

Andersherum können Sie linq2Sql die Zuordnung zu Ihren POCOs überlassen, indem Sie einen benutzerdefinierten Datenkontext erstellen und nicht den Designer für die Zuordnung verwenden :). Auf diese Weise halten Sie Ihr Domänenmodell sauber und lassen linq2Sql die Abhängigkeiten zum richtigen Zeitpunkt auffüllen.Beachten Sie, dass der Einstieg in diese Route seine eigenen Probleme mit sich bringt, aber machbar ist.

Hier ist ein Link, der Ihnen den Einstieg in diese Route erleichtert

Erzielen von POCOs in Linq to SQL

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top