8

ich die folgenden zwei Klassen haben:Fluent NHibernate One-To-Many Mapping

Anzeige

public virtual int Id { get; set; 
public virtual IList<AdvertImage> AdvertImages { get; set; } 

AdvertImage

public virtual int Id { get; set; } 
public virtual string Filename { get; set; 
public virtual Advert Advert { get; set; } 

In der DB, Tabelle meine AdvertImages hat die FK "AdvertId", die sich auf die Adverts-Tabelle bezieht, die den PK von "Id" hat.

Dies ist eine Eins-zu-Viele-Zuordnung, bei der eine Anzeige viele Bilder enthalten kann.

Meine Fluent NHibernate Zuordnungen (der Kürze halber bearbeitet) sind:

AdvertMap

Id(x => x.Id) 
    .GeneratedBy.Identity(); 
... 
HasMany(x => x.AdvertImages) 
    .KeyColumn("AdvertId") 
    .Inverse(); 
... 
Table("Adverts"); 

AdvertImageMap

Id(x => x.Id) 
    .GeneratedBy.Identity(); 
... 
References(x => x.Advert) 
    .Column("AdvertId"); 
... 
Table("AdvertImages"); 

Ich bin eine neue Instanz von Advert in Code erstellen, dann bevölkern die AdvertImages prope rty (der Anzeige) mit einer List<AdvertImage>.

Wenn ich gehe, um meine Advert Objekt an die DB, möchte ich die AdvertImages in ihre AdvertImages Tabelle eingefügt werden, aber aufgrund der Beziehung zwischen den 2 Tabellen, ich brauche die Insertion Insertion zuerst passieren, so als Die PK-ID wird generiert, die dann in die AdvertImages-Tabelle eingefügt werden kann. (Wenn ich meine Liste von AdvertImage erstelle, beziehe ich die Dateiname-Eigenschaft, aber habe offensichtlich zu diesem Zeitpunkt noch nicht die neue AdverdiD, möchte also, dass die Datei gefüllt wird, wenn die Anzeige in der Datenbank beibehalten wird).

Ich habe versucht, mit verschiedenen Inverse() und Cascade-Einstellungen experimentieren, aber noch nicht gelungen. Kann mir bitte jemand helfen?

Antwort

10

Sie benötigen Advert Zuordnung Kaskade zu ändern:

Id(x => x.Id) 
    .GeneratedBy.Identity(); 

HasMany(x => x.AdvertImages) 
    .KeyColumn("AdvertId") 
    .Inverse() 
    .Cascade.AllDeleteOrphan(); 

Table("Adverts"); 

Sie dann in der Lage sein sollte, so etwas zu tun, um eine Advert Objekt bestehen und es ist Kinder AdvertImage.

Advert newAdvert = new Advert(); 
AdvertImage newImage = new AdvertImage(); 
newImage.Advert = newAdvert; 
newAdvert.AdvertImages.Add(newImage); 

using(NHibernate.ISession session = SessionFactory.GetCurrentSession()) 
{ 
    using (NHibernate.ITransaction tran = session.BeginTransaction()) 
    { 
     session.Save(newAdvert); 
     tran.Commit(); 
    } 
} 

Meine Entitäten in der Regel enthalten Hinzufügen und Entfernen von Methoden für bidirektionale man viele Beziehungen wie folgt aus:

public class Advert 
{ 
    public virtual IList<AdvertImage> AdvertImages { get; set; } 

    public virtual void AddImage(AdvertImage newImage) 
    { 
     newImage.Advert = this; 
     AdvertImages.Add(newImage); 
    } 
} 
+0

Danke Cole W, und netter Tipp die Methoden hinzufügen und entfernen. – marcusstarnes

1

Was für mich funktioniert, ist normalerweise, die Fremdschlüsselspalte so zu setzen, dass Nullen in DB erlaubt sind - das wäre Ihre AdvertId-Spalte, aber ich bin mir nicht sicher, ob das in Ihrem Fall funktionieren würde, da Sie Identität verwenden. Was NHibernate tut, ist INSERT all mit einer Abfrage und aktualisiert dann die untergeordnete Tabellenspalte für Fremdschlüssel in die korrekte ID der übergeordneten Tabelle. Vielleicht würde es auch in deinem Fall funktionieren.

Hier einige ähnliche Frage, die helfen könnten: Cascade insert on one-to-many with fluent NHibernate

+1

Die Verbindung, die Sie eingeschlossen haben, macht keinen Sinn, da es nichts mit Fluent NHibernate zu tun hat. – Komengem

+0

@KomengeMwandila Obwohl die Antwort auf die Frage, die ich verknüpfte, Fluent NHibernate nicht verwendet, stellt sich die Frage. Fluent NHibernate fügt hier nichts Neues hinzu. Es bietet nur eine weitere Schnittstelle zum NHibernate-Mapping. Sobald Sie verstehen, wie das Mapping funktioniert, können Sie es auf Fluent NHibernate, XML-Mapping, Mapping von Code anwenden ... –

2

Ich hatte das gleiche Problem. Ich habe einige Zeit damit verbracht, alle Arten von Mappings auszuprobieren.Ich entdeckte dann, dass meine Zuordnungen in Ordnung waren, und es war tatsächlich, dass ich meine Sitzung in eine Transaktion verpacken musste und die Methode Commit() nach der Methode session.SaveOrUpdate() verwenden musste.

using(var session = sessionFactory.OpenSession()) 
using(var tx = session.BeginTransaction()) 
{ 
// execute code that uses the session 
tx.Commit(); 
} 
+0

danke ..gespart viel Zeit um dieses Problem zu graben –