2009-11-09 13 views
6

Ich habe zwei zugehörige Geschäftsobjekte - A und B. die Zuordnung ist (A-> B) viele-zu-eins, mit B.Id a Fremdschlüssel in A (also A hat A.B_id in der DB).NHibernate - Zugriff auf die ID eines verknüpften Objekts ohne Lazy Laden des gesamten Objekts

Ich benutze faul = true und löste die meisten meiner Probleme, aber in A's ToString möchte ich auch A.B.Id drucken, was ich ohne weitere Fahrten zur DB haben sollte. Der Zugriff auf A.B aktiviert den Proxy und löst eine Ausnahme aus, da dies nicht im Kontext einer geöffneten Sitzung liegt.

eine einfache, aber hässliche Lösung wäre A.B_id Eigenschaft zu haben. aber das ist Teil der Dinge, die wir in erster Linie vermeiden wollten. jeder "organische" Weg, dies zu tun? :) danke!


UPDATE: Lesen Sie nur über Caching und Session.Get vs Session.Load. bevor ich nur neu, dass man eine Ausnahme löst, wenn das Objekt nicht existiert (Session.Load), und das andere gibt ein Null-Objekt (Session.Get) zurück. Nach dem Lesen über Caching here ist es klar, dass Session.Load einen Proxy an das Objekt zurückgibt, und es nur träge holt, wenn auf eine andere Eigenschaft als die ID zugegriffen wird, was sehr ähnlich ist, was ich von Assoziationen brauche! für jetzt habe ich die einzelnen Objekt-IDs (hinzugefügt B_Id zu A, so kann ich es als A.B_Id Zugriff statt Abid zu verwenden)

+0

Warum möchten Sie dies tun? – Paco

+0

wie gesagt, nur für den Protokolldruck usw., in A's ToString(). Ich brauche keine anderen Felder von B. nur die ID. –

Antwort

3

Für die exakt gleichen Grund, warum ich meine vielen expliziten AB-ID-Eigenschaften verwendet haben, für alle -zu-eins-Beziehungen. Ich sehe das nicht als eine schnelle und schmutzige Lösung, da es eine Lösung für dieses Problem bietet, und auch viel Flexibilität ist der Bereich zum Speichern von Updates, dh ich muss das B-Objekt nicht einfach aus der Datenbank holen, um es A zuzuweisen Um die Verknüpfung zu erstellen, wenn ich die B_ID in einer Abfragezeichenfolge oder woanders habe.

Meine Mapping-Dateien useually wie folgt aussehen:

<property name="CreatorID" column="CreatorID" type="Int32" not-null="true" /> 
<many-to-one name="Creator" column="CreatorID" class="SystemUser" insert="false" update="false" cascade="none" /> 

Wie Sie eine der 2 Objekte sehen können muss nur gelesen werden NHibernate Senden 2 mal in dieser Spalte in der Datenbank zu vermeiden, wenn Einsätze oder updatas sind Ereignis. Das obige macht nur lesend (mit den Attributen insert = "false" update = "false") das Viele-zu-Eins-Objekt, aber Sie können stattdessen nur die CreatorID-Eigenschaft lesen, wenn Sie möchten.

Wenn Sie nur die Viele-zu-Eins-Eigenschaft haben, haben Sie in Ihrer Entitätsklasse A keine Eigenschaft, die den B.ID-Wert enthält. Die einzige Möglichkeit, dies zu erreichen, ist der Zugriff auf das B-Objekt, das den Proxy auslöst und eine Abfrage an die Datenbank auslöst (wenn sie nicht bereits in der Sitzung geladen ist).

Ich freue mich über jede andere Option, die eine Lösung bietet und die gleiche Flexibilität bietet.

+0

Ich wünschte immer noch, dass dies mit nur ABId getan werden könnte - ich mag die doppelten Daten nicht - ich hatte diese Eigenschaften und * entfernte * sie ... Ich werde die Angelegenheit weiter untersuchen, aber jetzt ist das, was ich tun werde . Vielen Dank! –

+0

@YonatanKarni Stimme voll und ganz zu. Es gibt auch ein großes Leistungsproblem. Fügen Sie einer Entitätssammlung (mit einem festgelegten Backing-Typ) eine große Anzahl n von 'Proxy'-Entitäten hinzu, und es wird die Leistung beendet, da n selects, eine pro proxy, sequenziell ausgeführt werden, wie es bei 'set.Add' der Fall ist Ding. – jasper

5

Wenn Sie NHibernate 3.2 oder höher verwenden, können Sie den folgenden Code verwenden, um die ID des zugehörigen Objekts ohne eine anderen Umlauf zur Datenbank zu bekommen das ganze Objekt zu laden: getIdentifier Methode von

using NHibernate.Proxy; 
... 
object id = null; 
if (obj.IsProxy()) // obj is the object you want to get its identifier. 
{ 
    var proxy = obj as INHibernateProxy; 
    if (proxy != null) 
    { 
     var li = proxy.HibernateLazyInitializer; 
     if (li != null) 
      id = li.Identifier; 
    } 
} 
1

Sie verwenden können Nhibernate Sitzung:

session.GetIdentifier(obj); 
Verwandte Themen