[NHibernate] member collectie wordt niet gesaved

Pagina: 1
Acties:

  • whoami
  • Registratie: December 2000
  • Laatst online: 00:06
Ik ben nog eens verder met NHibernate aan het spelen, en ik loop nu tegen het volgende.

Ik heb 2 classes, een class 'Container' en een class 'Item'.
Een container bevat items.

De container ziet er bv zo uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Container
{
   private int _containerId;
   private IList _items = new ArrayList();

   public int ContainerId
   {
        get { return _containerId; }
   }

   public IList Items
   {
       get {return _items; }
       set { _items = value; }
   }
}


Item:
code:
1
2
3
4
5
6
7
8
public class Item
{
     private int _itemId;
     private string _name;
     private Container _container;

     // properties weggelaten
}

Nu, als ik gewoon deze eenvoudige code uitvoer, dan wordt m'n container wel in m'n DB gesaved, maar de Items van die container niet.

code:
1
2
3
4
5
6
7
8
Container c = new Container();
Item it = new Item();
it.Name = "bliep";
c.Items.Add (it);

ISession s = AppSettings.Instance.SessionFactoryObj.OpenSession();

s.Save (c);


Ik zie echt niet in wat ik hier fout doe, of wat er voor zorgt dat m'n Items niet opgeslagen worden. Ik krijg ook geen excepties. :?

Het relevante gedeelte van m'n mapping files ziet er zo uit:
Container:
code:
1
2
3
4
5
6
7
<class name="TestApp.Container, TestApp" table="tblContainer">
  ...
  <bag name="Items">
     <key column="ContainerId"/>
     <one-to-many class="TestApp.Item, TestApp"/>
  </bag>
</class>


Item
code:
1
2
3
4
5
<class name="TestApp.Item" .... >
   ....
   <many-to-one name="Items" column="ContainerId"
                        class="TestApp.Container, TestApp" not-null="true"/>
</class>

https://fgheysels.github.io/


  • momania
  • Registratie: Mei 2000
  • Laatst online: 16:10

momania

iPhone 30! Bam!

XML:
1
2
3
4
5
6
7
<class name="TestApp.Container, TestApp" table="tblContainer">
  ...
  <bag name="Items" cascade="save-update">
     <key column="ContainerId"/>
     <one-to-many class="TestApp.Item, TestApp"/>
  </bag>
</class>

cascade="save-update" zou genoeg moeten zijn :)

Zie hier voor de verschillende strategien: http://www.hibernate.org/.../example-parentchild.html :)

[edit]
Even in java (anders snap ik het niet :+ ) zou je het zo moeten doen

In de Container methode toevoegen:
Java:
1
2
3
4
public void addItem(Item item) {
  item.setContainer(this);
  this.items.add(item);
}

Java:
1
2
3
4
5
Container c = new Container();
Item it = new Item();
it.setName("bliep");
c.addItem(it);
sess.save(c);

[ Voor 68% gewijzigd door momania op 11-11-2005 17:40 ]

Neem je whisky mee, is het te weinig... *zucht*


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:06
OK, dat werkt inderdaad, thx.

Thx voor de link, ik ga dat zeker eens doornemen.
momania schreef op vrijdag 11 november 2005 @ 17:35:
XML:
1
2
3
4
5
6
7
<class name="TestApp.Container, TestApp" table="tblContainer">
  ...
  <bag name="Items" cascade="save-update">
     <key column="ContainerId"/>
     <one-to-many class="TestApp.Item, TestApp"/>
  </bag>
</class>

cascade="save-update" zou genoeg moeten zijn :)

Zie hier voor de verschillende strategien: http://www.hibernate.org/.../example-parentchild.html :)

[edit]
Even in java (anders snap ik het niet :+ ) zou je het zo moeten doen

In de Container methode toevoegen:
Java:
1
2
3
4
public void addItem(Item item) {
  item.setContainer(this);
  this.items.add(item);
}

Java:
1
2
3
4
5
Container c = new Container();
Item it = new Item();
it.setName("bliep");
c.addItem(it);
sess.save(c);
Ik doe het idd ook ongeveer zo (ik heb een AddItem method die ervoor zorgt dat die Container ook in Item gezet wordt, etc...
Echter, in een ander voorbeeld in die link staat er in de mapping file alleen het 'inverse=true' attribute, en is die cascade nergens te bespeuren. Als ik het zo doe, dan wordt 'Item' ook niet gesaved. Ik snap er atm niet zoveel van...
Wat ik ook wel jammer vind, is dat die collectie eigenlijk volledig 'benaderbaar' is in m'n Container class dmv de getter/setter.
code:
1
2
3
4
5
6
7
8
9
class Container
{
   ..
   public IList Items
   {
         get {... }
         set {...}
   }
}

Waardoor het ook mogelijk is dat iemand gewoon dit doet:
code:
1
c.Items.Add( new Item());

ipv dit
code:
1
c.AddItem(new Item());


Anyway, ff die link bookmarken. :P

[ Voor 92% gewijzigd door whoami op 11-11-2005 17:50 ]

https://fgheysels.github.io/


  • momania
  • Registratie: Mei 2000
  • Laatst online: 16:10

momania

iPhone 30! Bam!

whoami schreef op vrijdag 11 november 2005 @ 17:46:
OK, dat werkt inderdaad, thx.

Thx voor de link, ik ga dat zeker eens doornemen.
Ik hoor wel vaker dat de documentatie van Hibernate zelf een stuk beter is dan NHibernate :)
Aangezien het eigenlijk hetzelfde is, kan je voortaan beter in de documentatie van Hibernate zelf kijken.
Enige waar je natuurlijk mee moet uitkijken is eventuele dingen die nog verschillen per versies, maar 99% komt wel overeen denk ik :)

Neem je whisky mee, is het te weinig... *zucht*


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:06
momania schreef op vrijdag 11 november 2005 @ 17:49:
[...]

Ik hoor wel vaker dat de documentatie van Hibernate zelf een stuk beter is dan NHibernate :)
Ja, dat denk ik ook....
'k heb hier ook het boek 'hibernate in action', maar zo'n ebook leest toch niet zo makkelijk vind ik. :P

https://fgheysels.github.io/


  • sig69
  • Registratie: Mei 2002
  • Laatst online: 20:41
Dat is inderdaad een vande nadelen dat NHibernate nog volop in ontwikkeling is, de documentatie loopt nog wel eens "iets" achter. Meestal bieden de Hibernate docs wel uitkomst idd.

Roomba E5 te koop


  • momania
  • Registratie: Mei 2000
  • Laatst online: 16:10

momania

iPhone 30! Bam!

whoami schreef op vrijdag 11 november 2005 @ 17:51:
[...]
'k heb hier ook het boek 'hibernate in action', maar zo'n ebook leest toch niet zo makkelijk vind ik. :P
Ik heb voor hibernate eigenlijk nog nooit een boek nodig geacht. De online reference is best compleet. En een hoop complexere zaken vind je vaak wel of in de faq's of met een paar clickjes op google :)

of hier op GoT :+

Neem je whisky mee, is het te weinig... *zucht*


  • tijn
  • Registratie: Februari 2000
  • Laatst online: 22-03 21:36
whoami schreef op vrijdag 11 november 2005 @ 17:46:
Echter, in een ander voorbeeld in die link staat er in de mapping file alleen het 'inverse=true' attribute, en is die cascade nergens te bespeuren. Als ik het zo doe, dan wordt 'Item' ook niet gesaved. Ik snap er atm niet zoveel van...
Op het moment dat je inverse="true" zet, geef je aan dat de objecten in de lijst (Item) er voor verantwoordelijk zijn dat de relatie Container-Item onderhouden wordt en niet de container. In dat geval wordt de relatie via Item.Container bepaald en zul je de Item objecten apart moeten saven of updaten, ongeacht cascade settings. Dit heeft te maken met het feit dat (N)Hibernate bij bidirectionele relaties niet kan gokken welke kant nou specifiek verantwoordelijk is voor het in stand houden van de relatie.

[ Voor 4% gewijzigd door tijn op 11-11-2005 18:33 ]

Cuyahoga .NET website framework


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

als je die IList enkel en alleen voor NHibernate gebruikt, kun je ze toch private maken...
daar kan NHibernate perfect mee overweg.
(of enkel een getter)

ASSUME makes an ASS out of U and ME


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:06
HIGHGuY schreef op vrijdag 11 november 2005 @ 19:35:
als je die IList enkel en alleen voor NHibernate gebruikt, kun je ze toch private maken...
daar kan NHibernate perfect mee overweg.
(of enkel een getter)
Hmm, idd.
Ik kan met de 'access' attribute aangeven dat er niet naar een property gemapped wordt, maar naar een field.
tijn schreef op vrijdag 11 november 2005 @ 18:32:
[...]


Op het moment dat je inverse="true" zet, geef je aan dat de objecten in de lijst (Item) er voor verantwoordelijk zijn dat de relatie Container-Item onderhouden wordt en niet de container. In dat geval wordt de relatie via Item.Container bepaald en zul je de Item objecten apart moeten saven of updaten, ongeacht cascade settings. Dit heeft te maken met het feit dat (N)Hibernate bij bidirectionele relaties niet kan gokken welke kant nou specifiek verantwoordelijk is voor het in stand houden van de relatie.
thx :)

[ Voor 46% gewijzigd door whoami op 11-11-2005 20:15 ]

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
tijn schreef op vrijdag 11 november 2005 @ 18:32:
Op het moment dat je inverse="true" zet, geef je aan dat de objecten in de lijst (Item) er voor verantwoordelijk zijn dat de relatie Container-Item onderhouden wordt en niet de container. In dat geval wordt de relatie via Item.Container bepaald en zul je de Item objecten apart moeten saven of updaten, ongeacht cascade settings. Dit heeft te maken met het feit dat (N)Hibernate bij bidirectionele relaties niet kan gokken welke kant nou specifiek verantwoordelijk is voor het in stand houden van de relatie.
Wat een rare opzet. Immers, de PK side is altijd de kant die verantwoordelijk is voor het in stand houden van een in-memory reference relatie voor cascaded saves, want pk-fk syncing vindt plaats nadat de pk side is gesaved, waarna je de fk side kunt saven etc.

Dus of ik nu doe:
myItem.Container = myContainer;
of
myContainer.Items.Add(myItem);
dat boeit niet, want na allebei de acties is de ander ook uitgevoerd en PK-FK syncing heeft dan plaatsgevonden indien de PK side niet nieuw is en indien de PK side wel nieuw is dan vind PK-FK syncing plaats transparant nadat de PK side gesaved is.

Overigens is dit geen bidirectionele relatie maar een 1:n relatie tussen Container en Item en een 1:n relatie heeft een counterrelatie m:1 Item - Container over dezelfde attributes. Een bidirectionele relatie is een relatie tussen twee entities over verschillende attributes, bv dat wanneer Container ook een reference zou hebben naar Item op 1:1 basis bv.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • tijn
  • Registratie: Februari 2000
  • Laatst online: 22-03 21:36
EfBe schreef op zaterdag 12 november 2005 @ 11:42:
[...]

Wat een rare opzet. Immers, de PK side is altijd de kant die verantwoordelijk is voor het in stand houden van een in-memory reference relatie voor cascaded saves, want pk-fk syncing vindt plaats nadat de pk side is gesaved, waarna je de fk side kunt saven etc.
Yep, als je de (vooral Hibernate) forums er op naslaat is dit zo'n beetje de issue die het meeste vragen oplevert. En als antwoord komt dan vaak niet meer als 'dat is nou eenmaal zo' en 'dat kunnen we wel gaan uitleggen, maar dat is veels te complex voor jullie'. Let wel dat dit vooral de java-Hibernate lui betreft. Bij NHibernate is het antwoord gewoon 'zo is het nou eenmaal ook bij Hibernate en we willen op dit punt niet gaan afwijken van onze grote broer' :).
Overigens is dit geen bidirectionele relatie maar een 1:n relatie tussen Container en Item en een 1:n relatie heeft een counterrelatie m:1 Item - Container over dezelfde attributes. Een bidirectionele relatie is een relatie tussen twee entities over verschillende attributes, bv dat wanneer Container ook een reference zou hebben naar Item op 1:1 basis bv.
Ok, klinkt aannemelijk. Ik heb het begrip bidirectioneel gebruikt omdat dit in Hibernate-resources ook altijd gebruikt wordt (en dan misschien foutief :)).

[offtopic]
Wat me overigens enorm opvalt (ook bij mezelf) is dat wanneer je uit een data-driven wereld afkomstig bent, je automatisch de neiging hebt om relaties 2 kanten op te maken (1:n en m:1). Ga je echter eens goed zitten voor je design dan kom je er achter dat het in veel gevallen volstrekt overbodig is.

Cuyahoga .NET website framework

Pagina: 1