Ik ben een beetje met NHibernate aan het spelen. Ik heb bv een class Customer. Die Customer heeft Orders. Orders worden lazy geladen, en hebben als cascade optie 'save-update'.
So far so good; alles werkt zoals ik het wil, behalve het saven dus.
Ik heb een WinForms applicatie:
Die applicatie bestaat uit een overzichtscherm van Customers. Als ik daar een Customer kies, kan ik een detail-scherm openen voor die Customer. Op dat moment wordt de customer uit de databank gehaald:
In de GetCustomer method van de repository, ga ik een ISession openen, de customer opladen, en de sessie opnieuw sluiten.
Op dit moment heb ik m'n Customer object in het geheugen zitten.
Stel nu dat ik een paar wijzigingen heb doorgevoerd aan attributen van de entiteit 'Customer', bv z'n naam. Echter, ik heb geen wijzigingen gedaan aan z'n Orders (ik heb deze enkel opgehaald).
Als ik dan op 'Save' klik, dan ga ik opnieuw een nieuwe ISession openen, de SaveOrUpdate method aanroepen en m'n customer-object als argument doorgeven.
Ook hier blijkt alles op het eerste zicht te werken zoals ik wil: de wijzigingen die ik doorgevoerd heb, worden ook in de DB gepersisteerd.
Echter, als ik even via Sql Profiler kijk wat er nu precies naar de DB gestuurd wordt, dan zie ik dat er ook UPDATE statements uitgevoerd worden voor m'n Order objecten die aan die Customer hangen, alhoewel ik deze niet gewijzigd heb.
Dat zal natuurlijk te maken hebben met het feit dat ik een andere ISession gebruik om m'n Customer op te slaan, en dat die ISession dus niet op de hoogte is van de 'state' van m'n objecten (dirty of niet). Dit is natuurlijk wel behoorlijk vervelend. Ik wil nl. niet dat er UPDATE statements uitgevoerd worden voor objecten die niet gewijzigd zijn.
Nu kan ik er natuurlijk wel voor zorgen dat de Save dezelfde ISession gaat gaan gebruiken als de Load, maar eigenlijk wil ik dit liever niet.
Dit zou nl. willen zeggen dat m'n ISession open blijft staan, zolang m'n CustomerDetailForm open staat.
M'n CustomerDetailForm zou dan bv deze code bevatten:
Voorbeeld code, ff niet op details letten zoals rollbacken etc...
Dit zou naar mijn mening natuurlijk perfect moeten werken, maar een elegante oplossing vind ik het niet.
Dit houdt nl. in dat m'n Repositories altijd dezelfde ISession moeten gebruiken voor het manipuleren van een entiteit. Zo ook bij het lazy-loaden van de Orders zal m'n repository dus moeten weten dat een bepaalde ISession moet gebruikt worden.
Is er een andere oplossing mogelijk ?
So far so good; alles werkt zoals ik het wil, behalve het saven dus.
Ik heb een WinForms applicatie:
Die applicatie bestaat uit een overzichtscherm van Customers. Als ik daar een Customer kies, kan ik een detail-scherm openen voor die Customer. Op dat moment wordt de customer uit de databank gehaald:
code:
1
| _customerObj = customerRepositoryObj.GetCustomer (id); |
In de GetCustomer method van de repository, ga ik een ISession openen, de customer opladen, en de sessie opnieuw sluiten.
Op dit moment heb ik m'n Customer object in het geheugen zitten.
Stel nu dat ik een paar wijzigingen heb doorgevoerd aan attributen van de entiteit 'Customer', bv z'n naam. Echter, ik heb geen wijzigingen gedaan aan z'n Orders (ik heb deze enkel opgehaald).
Als ik dan op 'Save' klik, dan ga ik opnieuw een nieuwe ISession openen, de SaveOrUpdate method aanroepen en m'n customer-object als argument doorgeven.
Ook hier blijkt alles op het eerste zicht te werken zoals ik wil: de wijzigingen die ik doorgevoerd heb, worden ook in de DB gepersisteerd.
Echter, als ik even via Sql Profiler kijk wat er nu precies naar de DB gestuurd wordt, dan zie ik dat er ook UPDATE statements uitgevoerd worden voor m'n Order objecten die aan die Customer hangen, alhoewel ik deze niet gewijzigd heb.
Dat zal natuurlijk te maken hebben met het feit dat ik een andere ISession gebruik om m'n Customer op te slaan, en dat die ISession dus niet op de hoogte is van de 'state' van m'n objecten (dirty of niet). Dit is natuurlijk wel behoorlijk vervelend. Ik wil nl. niet dat er UPDATE statements uitgevoerd worden voor objecten die niet gewijzigd zijn.
Nu kan ik er natuurlijk wel voor zorgen dat de Save dezelfde ISession gaat gaan gebruiken als de Load, maar eigenlijk wil ik dit liever niet.
Dit zou nl. willen zeggen dat m'n ISession open blijft staan, zolang m'n CustomerDetailForm open staat.
M'n CustomerDetailForm zou dan bv deze code bevatten:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| public class CustomerDetailForm
{
private ISession _sessionObj;
private Customer _customerObj;
protected override void Execute( int id )
{
_sessionObj = sessionFactoryObj.OpenSession();
_customerObj = customerRepositoryObj.GetCustomer (_sessionObj, id);
_sessionObj.Connection.Close();
}
protected override void OkButtonClicked()
{
_sessionObj.Reconnect();
_sessionObj.BeginTransaction();
customerRepositoryObj.SaveCustomer (_sessionObj, _customerObj);
_sessionObj.Transaction.Commit();
_sessionObj.Close();
}
} |
Voorbeeld code, ff niet op details letten zoals rollbacken etc...
Dit zou naar mijn mening natuurlijk perfect moeten werken, maar een elegante oplossing vind ik het niet.
Dit houdt nl. in dat m'n Repositories altijd dezelfde ISession moeten gebruiken voor het manipuleren van een entiteit. Zo ook bij het lazy-loaden van de Orders zal m'n repository dus moeten weten dat een bepaalde ISession moet gebruikt worden.
Is er een andere oplossing mogelijk ?
[ Voor 4% gewijzigd door whoami op 01-03-2006 21:42 ]
https://fgheysels.github.io/