2009-04-01 9 views
9

Ich bin sicher, dass dies eine einfache Frage ist aber Folgendes beachten: ich einen Bezug zwischen Unternehmen und Sektoren haben wie folgt:Fluent NHibernate - Wie die Fremdschlüsselspalte als Eigenschaft zur Karte

public class Company { 
    public Guid ID { get; set; } 
    public Sector Sector { get; set; } 
    public Guid SectorID { get; set; } 
} 

public class Sector { 
    public Guid ID { get; set; } 
    public string Name { get; set; } 
} 

Ok. Was ich will, ist die SectorID der Gesellschaft Objekt gefüllt werden, nachdem ich gehen:

(new Company()).Sector = new Sector() { Name="asdf" } 

und machen Sie einen Flush.

Das von mir verwendete Mapping erstellt freundlicherweise eine zusätzliche Spalte in der Datenbank mit der Bezeichnung "Sector_Id" in der Tabelle Company, die jedoch nicht als Eigenschaft für Company verfügbar ist. Ich möchte, dass die SectorID-Eigenschaft gefüllt wird.

Die Abbildung ich zur Zeit in der CompanyMap bin mit ist

References(c => c.Sector).Cascade.All(); 

jemand irgendwelche Ideen Hat?


Vielen Dank für Ihre Antwort. Leider, wenn ich die zweite Option zu tun (den Spalt Name der Spalte die gleiche wie die Eigenschaft zu sein, oder setzen Sie Map(x => x.SectorID, "Sector_Id") dann bekomme ich den Fehler:

System.IndexOutOfRangeException: ungültigen Index 7 für diese SqlParameterCollection mit Count = 7.

Ich muss möglicherweise die erste Option tun, aber ich bin besorgt, dass eine zusätzliche Abfrage ausgelöst wird, wenn Sie die SectorID abrufen, wie es den Sektor selbst aus der db bekommt (es sei denn, es ist eifrig geladen, die a ist) ein wenig Ärger)

Ich bin überrascht, dass es keine einfache Antwort darauf gibt.


WOW! Wenn ich

public virtual Guid SectorID 
{ 
    get { return Sector.ID; 
} 

verwenden dann ist nhibernate klug genug, um zu wissen, dass die Sector_id Spalte in der Organisation Abfrage eigentlich das gleiche wie Sector.ID ist und es gibt diese unter den Hauben. Es sendet keine zusätzliche Abfrage, selbst wenn Sie faul laden. Ich bin beeindruckt!


Als Follow-up ... Es scheint, dass Hibernate nicht wirklich in der Lage sein geschrieben wird, um die Fremdschlüsselspalte in den Objekten abzubilden. Obwohl dies in Web-Frontends ein wenig schmerzhaft sein kann, macht es Sinn, da es sich hier wirklich um ein beharrliches Anliegen handelt, nicht wirklich um ein Objekt. Ich benutze asp.net MVC und habe ein benutzerdefiniertes Modell Binder geschrieben, die ein Eingabefeld mit dem Namen Kontakt (statt ContactID) nehmen, einen neuen Kontakt mit der ID von dem, was in der Texbox ist, und wenden Sie das an die Eigenschaft des Modells. Dies löst das Problem mit Dropdown-Listen in Web-Frontends. Wird Code eingeben, wenn jemand interessiert ist.

Antwort

2

Zwei Gedanken: Erstens, würde so etwas nicht erreichen, was Sie wollen?

public class Company { 
    public Guid ID { get; set; } 
    public Sector Sector { get; set; } 
    public Guid SectorID { 
     get { return Section.ID; } 
     // Really not sure what behavior your setter should have here; Maybe it shouldn't even have one? 
     set { Sector = new Sector { ID = value }; } 
    } 
} 

Zweitens, wenn Sie sagen, dass die Abbildung eine Spalte in der DB genannt Sector_Id erstellt ist, dass auf eine Säule zusätzlich, dass Sie SectorID Namen erstellt?Wenn dies der Fall ist, können Sie den Spaltennamen so ändern, dass er den korrekten Namen verwendet (here's the documentation for mappings, siehe einige Überschriften unter "Angabe des Spaltennamens").

Auch Mapping der SectorID-Eigenschaft (z. B. "Map (x => x.SectorID," Sector_Id ")")?

2

Steve Sie benötigen keine ForeignKey-Eigenschaft in der POCO-Klasse.

Zum Beispiel, wenn Sie versuchen, ID des Artikels Autor bekommen keine Join Auswahl durchgeführt werden.

var authorID = Article.Author.ID

13

Dies ist leicht mit einer Formel Eigenschaft getan.

public class Company { 
    public virtual Guid Id { get; set; } 
    public virtual Guid? SectorId { get; set; } 
    public virtual Sector Sector { get; set; } 
} 

public class CompanyMap : ClassMap<Company> { 
    public CompanyMap() { 
    Id(x => x.Id); // Maps to a column named "Id" 
    References(x => x.Sector); // Maps to a column named "Sector_id", unless you change the NHibernate default mapping rules. 
    Map(x => x.SectorId).Formula("[Sector_id]"); 
    }  
} 

Dies sollte genau so, wie Sie wollen. Wenn Company neu ist, wird SectorId Null sein; Wenn Company aus der Datenbank abgerufen wird, wird SectorId mit dem angegebenen Formelwert ausgefüllt. Die SectorId ist als eine Eigenschaft verfügbar, die es wirklich nett macht, mit Web-Dropdowns usw. umzugehen. Wenn Sie speichern, müssen Sie immer noch die "echte" Verknüpfung binden. Unter der Annahme, dass SectorId in einer Form ausgewählt wurde ...

using (var txn = session.BeginTransaction()) { 
    // Set the FK reference. 
    company.Sector = session.Load<Sector>(company.SectorId); 
    // Save the new record. 
    session.Save(company); 
    // Commit the transaction. 
    txn.Commit(); 
} 
+0

Ich gebe Ihnen Punkte für die Lösung des Fehlers war ich immer, aber dies scheint völlig nicht-intuitiv. Es scheint ein Entwurfsproblem in NHibernate zu sein, wenn es ein solches allgemeines Szenario nicht behandeln kann, da sowohl die FK ID als auch die zugehörige Objektinstanz als Eigenschaften vorliegen. –