2009-07-29 5 views
2

Ich habe eine Datamapper-Klasse, die eifrig jede Eigenschaft lädt, die kein Lazy-Attribut hat. Ich habe zwei Entitäten, Staat und Land, Land hat eine umgekehrte Beziehung zum Staat, in dem es eine Liste aller Staaten dieses Landes enthält und Staat hat eine Vorwärtsbeziehung zu Land, in dem es eine Eigenschaft Land hat, die das Land das eifrig lädt es ist zugeordnet. wenn ich jedoch versuchen, eines dieser Objekte abzurufen, können Sie einen Staat sagen, das ist, was passiert:Wie kann ich die Abruftiefe eines geladenen Datamappers steuern?

  1. Staat wird geladen von Mapper
  2. Mapper erreicht eine eifrige Eigenschaft Land
  3. Mapper ruft das Land für diesen Zustand
  4. Mapper lädt das Land
  5. Mapper einen eifrigen Sammlung Eigentum der Staaten, wo die Cache mit
  6. Mapper lädt eine Liste von Staaten und beginnt Abbilden jedes einzelnen erreicht man kann es.
  7. GOTO 1 für jeden Staat in Land

ich ratlos bin geladen, wie ich diese Schleife zu vermeiden. Hauptsächlich suche ich nach Ideen. Ich werde jeden Code posten, den jemand fragt, aber dieser Prozess umfasst VIEL Zeilen Code, also wollte ich die Frage nicht mit Code überfluten.

Vielen Dank im Voraus!

Edit:

Ordnung nach Beratung Matt Howells folgenden und Untersuchung tiefer in die DataMapper Muster Martin Fowler in der Tat zu einem zyklischen Bezug auf Seite 169 und 170. Sein Vorschlag ein leeres Objekt wird verwenden, und es spricht laden in eine Identity Map und gibt sie zurück, wodurch das rekursive Laden gestoppt wird. Ich habe diesen Absatz ungefähr 1000 Mal gelesen und ich verstehe immer noch nicht, wie dies die Ladung stoppt und darüber hinaus bin ich verloren, wann oder wie ich wissen würde, wann ich dieses leere Objekt in meine Identitätskarte laden soll. Ich entschuldige mich dafür, dass ich hier dicht bin, aber das scheint einfach über meinen Kopf zu fliegen.

Nochmals vielen Dank.

Antwort

2

Betrachten Sie das Laden von Objekten über ein Repository, das verfolgt, welche Objekte geladen wurden.

Edit: Wenn Sie Ihren eigenen ORM machen (und auch wenn Sie nicht sind) empfehle ich Martin Fowlers Buch Patterns of Enterprise Application Architecture. Ich erinnere mich vage daran, dass er über diese Loop-Situation in dem Buch gesprochen hat, damit es dir helfen könnte.

Bearbeiten 2: In den Schritten 4 und 5 Ihrer Schleife, wenn Sie das Land bereits geladen haben, dann ist es nicht erforderlich, seine Zustände zu laden, weil sie bereits geladen werden sollten. Dies unterbricht die Endlosschleife.

+0

Ich verfolge tatsächlich alle Objekte, die geladen wurden. Allerdings, und ich denke, ich bin nur dicht, ich bin nicht in der Lage zu sehen, wie ich das nutzen kann. Ich versuche die Abruftiefe zu kontrollieren, aber sie muss spezifisch für einen Urheber kontrolliert werden. Was ich versuche zu erreichen, ist im Wesentlichen: Staat (Urheber) -> Land -> Staaten -> [STOP], aber wenn ich jeden einzelnen Staat in Staaten abbilde, haben die Entitäten kein Konzept der Existenz des Urhebers des Antrags . Es scheint also, dass die Anwendung eines Zählers, der für den Urheber spezifisch ist, nicht in Frage kommt. Ja? – joshlrogers

+0

Ich habe es auf meinem Schreibtisch bei der Arbeit, werde sehen, ob ich morgen etwas finden kann. Vielen Dank. – joshlrogers

+0

Ich habe Martin Fowlers Rat hinzugefügt, aber ich bin immer noch verloren. Irgendein Rat? – joshlrogers

1

Der Datamapper sollte kreisförmige Referenzen abfangen. Ist es ein selbstgebauter Datamapper?

+0

Es ist homegrown ..... wie würde ich irgendeine Form des Fangs für das implementieren? Das ist der Punkt, an dem ich meinen Datamapper-Code nicht anpassen kann, um eine Uhr dafür einzubauen. – joshlrogers

+0

Notieren Sie die bereits besuchten Eigenschaften und vergleichen Sie die aktuelle Eigenschaft mit dieser Liste. – EricSchaefer

+0

Also wird die Abruftiefe normalerweise auf der Eigenschaftsebene und nicht auf der Objektebene implementiert? Also sagen wir, meine maximale Abruftiefe ist 3, also könnte die Eigenschaft 3 mal abgebildet werden, aber die Tiefe des Objektgraphen könnte wesentlich höher sein. Habe ich diese Annahme richtig? – joshlrogers

0

Ich wollte nur die Lösung, die ich gefunden habe, aber ich glaube, es gibt viele Möglichkeiten, diese Katze zu häuten.

Hier ist meine FetchDepthCounterClass ich erstellt:

public static class FetchDepthCounter 
{ 
    private static Dictionary<Type, int> _DepthCounter; 
    private static int _MaxDepth = 3; 

    static FetchDepthCounter() 
    { 
     _DepthCounter = new Dictionary<Type, int>(); 
    } 

    public static void SetDepth(int depth) 
    { 
     _MaxDepth = depth; 
    } 

    public static void ResetCounter() 
    { 
     _DepthCounter.Clear(); 
    } 

    public static bool IncrementCounter(Type entityType) 
    { 
     if(!_DepthCounter.ContainsKey(entityType)) 
     { 
      _DepthCounter.Add(entityType, 0); 
      return true; 
     } 

     if(_DepthCounter[entityType] < _MaxDepth) 
     { 
      ++_DepthCounter[entityType]; 
      return true; 
     } 

     return false; 
    } 

} 

IncrementCounter eine Bool zurückgibt besagt, ob die maximale Abruftiefe erreicht wurde oder nicht.Ich nenne Inkrementzähler als Teil meines Mapping-Prozesses, kurz bevor ich den Wert der Eigenschaft festlege. Zuerst stelle ich fest, dass das, was ich laden muss, ein anderes DTO-Objekt oder eine Sammlung von DTOs ist, und übergebe den übergeordneten Typ und inkrementiere diesen Typ. Das ist also das klein bisschen Code in meiner SetValue-Methode in meinem DataMapper:

if(isDto) 
{ 
    if (!FetchDepthCounter.IncrementCounter(property.ComponentType)) 
     return; 
} 

dass es ist, dass es zu tun scheint. Alle meine Unit Tests sind vorüber. Danke für die Hilfe von allen. Ich hoffe, dass dies später jemandem hilft. Noch einmal, es wäre wahrscheinlich viel einfacher gewesen, es in ein Arbeitseinheitsmuster zu verpacken, und vielleicht werde ich das auch tun, aber das macht den Job für den Moment erledigt.

Verwandte Themen