mon domaine est un aéroport, qui contient plusieurs terminaux, et chaque terminal contient des zones etc.
étant donné que le nombre d'entités aéroport/terminal/zone est très petit, je voudrais:
1. charger toute la hiérarchie avec impatience lors de la récupération d'un aéroport.
(en utilisant la configuration suivante couramment:
nHibernate chargement impatient- comportement de mise à jour étrange
//eagerly load terminals
mapping.HasMany(x => x.Terminals).Not.LazyLoad()
.Cache.ReadWrite();
)
2. permettent la mise en cache de niveau 2, de sorte que tous les récupérations d'un objet de l'aéroport ne serait pas frapper la DB.
le chargement et la mise en cache désirés fonctionnent bien, mais le test suivant produit un comportement étrange.
(le code suivant récupère une entité de l'aéroport deux fois (ne pas frapper la DB la deuxième fois) et met à jour l'un d'entre eux.)
[TestMethod]
public void TestSecondLevelCache()
{
Airport firstAirport = null, secondAirport = null;
Console.WriteLine("first select");
using (ISession session = this.SessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
//the idea here is to see whether there are two calls to DB here. check the sql output
AirportDAO dao = new AirportDAO(session);
firstAirport = dao.GetAirport();
transaction.Commit();
}
}
Console.WriteLine("second select");
using (ISession session = this.SessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
//the idea here is to see whether there are two calls to DB here. check the sql output
AirportDAO dao = new AirportDAO(session);
secondAirport = dao.GetAirport();
transaction.Commit();
}
}
Console.WriteLine("Are those the same airport instance? " + firstAirport.Equals(secondAirport));
Console.WriteLine("now adding a terminal");
using (ISession session = this.SessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
secondAirport.Terminals.Add(new Terminal() { Name = "terminal added to second airport", Zones = new List<Zone>() });
session.Update(secondAirport);
transaction.Commit();
}
}
//this Assert fails, since firstAirport != secondAirport
Assert.IsNotNull(firstAirport.Terminals.FirstOrDefault(t => t.Name.Contains("second airport")));
}
voir la sortie résultante:
sélectionnez d'abord .
NHibernate: SELECT airport0_.Id comme Id36_0_, airport0_.Name comme Name36_0_, airport0_.IsDeleted comme IsDeleted36_0_ dE dbo [Airport] airport0_ OÙ [email protected]; @ p0 = 1
NHibernate: SE LECT terminals0_.Airport_id comme Airport4_1_, terminals0_.Id comme Id1_, terminals0_.Id comme Id50_0_, terminals0_.Name comme Name50_0_, terminals0_.IsDeleted comme IsDeleted50_0_, terminals0_.Airport_id comme Airport4_50_0_ FROM dbo. [Terminal] terminaux0_ WHERE [email protected] .; @ p0 = 1
NHibernate: SELECT zones0_.Terminal_id comme Terminal4_1_, zones0_.Id comme Id1_, zones0_.Id comme Id51_0_, zones0_.Name comme Name51_0_, zones0_.IsDeleted comme IsDeleted51_0_, zones0_.Terminal_id comme Terminal4_51_0_ à partir de DBO [ zone] zones0_ OÙ [email protected]; @ p0 = 2
deuxième sélectionnez
Sont ceux de la même instance de l'aéroport? Faux
ajoutant maintenant un terminal
NHibernate: sélectionner next_hi de dbo._uniqueKey avec (UPDLOCK, rowlock)
NHibernate: mise à jour dbo._uniqueKey défini next_hi = @ p0 où next_hi = @ p1; p0 = @ 17 @ NHibernate: INSERT INTO dbo. [Terminal] (Nom, IsDeleted, Airport_id, Id) VALEURS (@ p0, @ p1, @ p2, @ p3), @ p0 = 'terminal ajouté au deuxième aéroport', p1 = 16
@ p1 = Faux, @ p2 = NULL, @ p3 = 16
NHibernate: UPDATE dbo. [Aéroport] SET Nom = @ p0, IsDeleted = @ p1 OERE ID = @ p2; @ p0 = 'aéroport d'essai', @ p1 = Faux, @ p2 = 1
NHibernate: UPDATE dbo. [T erminal] SET Nom = @ p0, IsDeleted = @ p1, Airport_id = @ p2 O WH Id = @ p3; @ p0 = 'terminal de test', @ p1 = Faux, @ p2 = 1, @ p3 = 2
NHibernate: UPDATE dbo. [Zone] SET Nom = @ p0, IsDeleted = @ p1, ID_terminal = @ p2 O Id Id = @ p3; @ p0 = 'zone de test', @ p1 = Faux, @ p2 = 2, @ p3 = 3
NHibernate: MISE À JOUR dbo.[Terminal] SET Airport_id = @ = p0 où id @ p1; @ p0 = 1, @ p1 = 16
mes problèmes sont les suivants: 1.
le comportement de mise à jour étrange qui met à jour tout .. .
2. le fait que firstAirport et secondAirport ne sont pas le même objet (peut-être que je manque quelque chose cache de niveau 2?)
merci à l'avance,
Jhonny
Merci! cela semble fonctionner. Aussi, à propos de firstAirport! = SecondAirport, mon but était de voir si lorsqu'une session met à jour un aéroport, l'autre session le voit immédiatement (sans appeler Get()). Je vois maintenant que c'est une supposition tout à fait ridicule. Évidemment, si je veux voir les changements faits à un objet par une session différente, je dois charger cet objet encore. –
également, consultez la solution d'Ayende, en utilisant Merge() - http://ayende.com/Blog/archive/2009/11/08/nhibernate-ndash-cross-session-operations.aspx –