мой домен - это аэропорт, который содержит несколько терминалов, и каждый терминал содержит зоны и т. Д.
так как количество объектов аэропорта / терминала / зоны очень мало, я бы хотел:
1. загружать всю иерархию при поиске в аэропорту.
(используя следующую свободную конфигурацию:
//eagerly load terminals
mapping.HasMany(x => x.Terminals).Not.LazyLoad()
.Cache.ReadWrite();
)
2. включить кэширование 2-го уровня, чтобы все извлечения объекта аэропорта не попадали в БД.
энергичная загрузка и кэширование работают нормально, но следующий тест вызывает странное поведение.
(следующий код извлекает объект аэропорта дважды (без повторного обращения к БД) и обновляет один из них.)
[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")));
}
смотри полученный результат:
первый выбор
NHibernate: ВЫБЕРИТЕ airport0_.Id как Id36_0_, airport0_.Name как Name36_0_, airport0_.IsDeleted as IsDeleted36_0_ ИЗ dbo. [Аэропорт] airport0_ WHERE airport0_.Id=@p0; @ p0 = 1
NHibernate: ВЫБРАТЬ терминалы 0_.Airport_id в качестве Airport4_1_, Terminal 0_.Id в качестве Id1_, Terminal0_.Id в качестве Id50_0_, Terminal0_.Name в качестве имени50_0_, TerminalS__I. @ p0; @ p0 = 1
NHibernate:. ВЫБРАТЬ zones0_.Terminal_id, как Terminal4_1_, zones0_.Id как Id1_, zones0_.Id как Id51_0_, zones0_.Name как Name51_0_, zones0_.IsDeleted как IsDeleted51_0_, zones0_.Terminal_id как Terminal4_51_0_ ИЗ DBO [Зона] zones0_ ГДЕ zones0_.Terminal_id = @ p0; @ p0 = 2
второй выбор
Это один и тот же аэропорт? Ложные
Теперь добавляем терминал
NHibernate: выберите next_hi из dbo._uniqueKey с помощью (updlock, rowlock)
NHibernate: обновить dbo._uniqueKey set next_hi = @ p0, где next_hi = @ p1; @ p0 = 17, @ p1 = 16
NHibernate: INSERT INTO dbo. [Terminal] (Имя, IsDeleted, Airport_id, Id) ЗНАЧЕНИЯ (@ p0, @ p1, @ p2, @ p3); @ p0 = 'терминал добавлен во второй аэропорт', @ p1 = False, @ p2 = NULL, @ p3 = 16
NHibernate: ОБНОВЛЕНИЕ dbo. [Аэропорт] SET Name = @ p0, IsDeleted = @ p1 WHERE Id = @ p2; @ p0 = 'тестовый аэропорт', @ p1 = False, @ p2 = 1
NHibernate: ОБНОВЛЕНИЕ dbo. [Терминал] SET Name = @ p0, IsDeleted = @ p1, Airport_id = @ p2 WHERE Id = @ p3; @ p0 = 'тестовый терминал', @ p1 = False, @ p2 = 1, @ p3 = 2
NHibernate: ОБНОВЛЕНИЕ dbo. [Zone] SET Name = @ p0, IsDeleted = @ p1, Terminal_id = @ p2 WHERE Id = @ p3; @ p0 = 'тестовая зона', @ p1 = False, @ p2 = 2, @ p3 = 3
NHibernate: ОБНОВЛЕНИЕ dbo. [Терминал] SET Airport_id = @ p0 WHERE Id = @ p1; @ p0 = 1, @ p1 = 16
мои проблемы:
1. странное поведение обновления, которое обновляет все ...
2. тот факт, что firstAirport и secondAirport не являются одним и тем же объектом (может быть, я что-то упускаю из-за кэша 2-го уровня?)
заранее спасибо
Jhonny