[NHibernate] NHibernate wil m'n primary key updaten ?

Pagina: 1
Acties:

  • whoami
  • Registratie: December 2000
  • Laatst online: 07-04 22:26
Ik ben nog wat met NHibernate aan het spelen, en ik zit met het volgende:

Ik heb een class 'Customer' die een collectie heeft van 'Orders', en een Order bestaat dan weer uit OrderLines.

Als ik een nieuw Order wil ingeven, dan selecteer ik een Customer, add een nieuw order aan de customer, en voeg order-lines toe aan het order. Dan save ik de customer gewoon via een ISession.SaveOrUpdate().

De Sql die NHibernate genereert is dit:
code:
1
2
3
exec sp_executesql N'INSERT INTO tblOrder (CustomerId, OrderDate) VALUES (@p0, @p1); select SCOPE_IDENTITY()', N'@p0 int,@p1 datetime', @p0 = 2, @p1 = 'Mar 11 2006  5:10:50:000PM'

exec sp_executesql N'INSERT INTO tblOrderLine (NumberOfItems, ItemPrice, ArticleId, OrderId) VALUES (@p0, @p1, @p2, @p3); select SCOPE_IDENTITY()', N'@p0 int,@p1 decimal(19,5),@p2 int,@p3 int', @p0 = 1, @p1 = 874.00000, @p2 = 2, @p3 = 5

Wat gewoon goed is.
Echter, ik zie ook dat deze query gegenereerd wordt:
code:
1
exec sp_executesql N'UPDATE tblOrder SET Id = @p0 WHERE Id = @p1', N'@p0 int,@p1 int', @p0 = 2, @p1 = 5

Hierdoor loopt het boeltje natuurlijk mis.
Ik snap niet hoe hij erbij komt om dit te doen.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 07-04 22:26
Ik heb het ondertussen opgelost. :+ Echter, ik heb er toch nog eenvraag over.
De fout zat 'm blijkbaar in m'n mapping file.

Voor de customer class zag die er als volgt uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
  <class name="ShopDomain.Customer, ShopDomain" table="tblCustomer">
    <id name="id" access="field" column="Id" type="Int32" unsaved-value="-1">
      <generator class="identity"/>
    </id>
    <property name="Name" column="Name"/>
    <property name="Adress" column="Adress"/>
    <property name="City" column="City"/>
    <property name="Id" update="false" insert="false" />
    <bag name="orders" access="field" cascade="save-update" lazy="true">
      <key column="Id"/>
      <one-to-many class="ShopDomain.Order, ShopDomain"/>
    </bag>
  </class>


Ik heb de key columnn attribute van de bag 'orders' gewijzigd:
code:
1
2
3
4
    <bag name="orders" access="field" cascade="save-update" lazy="true">
      <key column="CustomerId"/>
      <one-to-many class="ShopDomain.Order, ShopDomain"/>
    </bag>


En daarmee was de foutmelding opgelost (de gegenereerde update query ging nl. m'n primary key gaan updaten, wat SQL Server trouwens niet toeliet aangezien het om een identity column gaat, en IDENTITY_INSERT off staat.

Echter, die UPDATE queries blijven bestaan. Die worden gegenereerd, terwijl dit imo eigenlijk niet nodig is.
De gegenereerde queries zien er zo uit:
Eerst 2 insert commands, die het order en de bijhorende orderline inserten:
code:
1
2
3
4
5
6
7
8
9
10
11
exec sp_executesql N'INSERT INTO tblOrder (CustomerId, OrderDate) 
VALUES 
(@p0, @p1); select SCOPE_IDENTITY()', 
N'@p0 int,@p1 datetime', 
@p0 = 2, @p1 = 'Mar 11 2006  6:05:00:000PM'

exec sp_executesql N'INSERT INTO tblOrderLine (NumberOfItems, ItemPrice, ArticleId, OrderId)
VALUES 
(@p0, @p1, @p2, @p3); select SCOPE_IDENTITY()', 
N'@p0 int,@p1 decimal(19,5),@p2 int,@p3 int', 
@p0 = 1, @p1 = 45.00000, @p2 = 1, @p3 = 7


En daarna worden er 2 UPDATE commands gelanceerd:
code:
1
2
3
exec sp_executesql N'UPDATE tblOrder SET CustomerId = @p0 WHERE Id = @p1', N'@p0 int,@p1 int', @p0 = 2, @p1 = 7

exec sp_executesql N'UPDATE tblOrderLine SET OrderId = @p0 WHERE Id = @p1', N'@p0 int,@p1 int', @p0 = 7, @p1 = 5


Aangezien de relaties al goed zijn (zie de insert queries) , en die update queries dus eigenlijk niets extra doen, zou ik deze liever achterwege laten. Is er een manier om dit te doen ?
En waarom doet NHibernate dit eigenlijk ?

https://fgheysels.github.io/


  • tijn
  • Registratie: Februari 2000
  • Laatst online: 22-03 21:36
Zet je toevallig de parent property van de objecten in de child collection om aan te geven bij welke parent een child hoort (bijv. Customer property van een Order object)? In dat geval moet je even inverse="true" aan de mapping van de bag toevoegen om aan te geven dat de relatie niet nog eens via de andere kant gezet hoeft te worden.

Cuyahoga .NET website framework


  • whoami
  • Registratie: December 2000
  • Laatst online: 07-04 22:26
Hmm, idd. Dit lost het idd op. thx.

Ik heb idd een 'AddOrder' method op m'n Customer class, die het Order toevoegt aan de collection class, en meteen ook de 'Custoler' property van de Order zet.

Echter, ik heb ook nog een public property 'Orders' op m'n customer class, dus eigenlijk laat dit toe dat je nog een 'fout' kan maken, nl. customer.Orders.Add (anorder) oproepen, ipv customer.AddOrder(anOrder);

Ik kan die Orders property natuurlijk private ofzo maken (ik heb deze nog nodig, aangezien ik daar iets doe mbt lazy-loading), maar dan moet ik wel een aantal extra methods / properties op de Customer class implementern (RemoveOrder, OrderCount, een method die een array van Orders teruggeeft), etc...
Hoe pakken jullie dat aan ?

https://fgheysels.github.io/


  • tijn
  • Registratie: Februari 2000
  • Laatst online: 22-03 21:36
Ik zou het pragmatisch aanpakken en gewoon die AddOrder() houden en tevens ook de Orders property pulic laten. Misschien wat minder netjes, maar zo lang duidelijk is dat Orders via AddOrder aangemaakt moeten worden lijkt het me geen probleem.
Dezelfde situaties kom je ook wel eens in Framework classes tegen en ik merk aan mezelf dat ik eerst op zoek ga naar een eventuele geschikte method voordat ik direct met de collection property aan de slag ga.

Cuyahoga .NET website framework