Использует ли NHibernate интернирование объектов? - PullRequest
0 голосов
/ 28 мая 2011

Почему этот код работает?

Использует ли NHibernate интернирование объектов?

Если нет, работает следующее, потому что перегрузка NHibernate равна оператору?

foreach (var c in s.Query<Country>())
{
    Console.WriteLine("\n{0}", c.CountryName);

    // code in question 
    foreach(var p in s.Query<Person>().Where(x => x.Country == c) )
        Console.WriteLine("{0}", p.PersonName);

}

Ответы [ 2 ]

0 голосов
/ 28 мая 2011

Полагаю, можно получить «ложное» заключение о том, что Hibernate использует интернирование объектов при использовании Linq.Поскольку это тоже работает (то есть создает строки):

foreach (var c in s.Query<Country>())
{
    Console.WriteLine("\n{0}'s people", c.CountryName);

    // different memory copy
    var cx = new Country { CountryId = 1 };


    foreach(var p in s.Query<Person>().Where(x => x.Country == cx) )
        Console.WriteLine("{0}", p.PersonName);
}

Поставщик Linq-to-db в NHibernate не заботится о других полях сущности при сравнении объектов (на самом деле, вещи сравниваются в DB-уровень, а не объекты), он сравнивает только идентификатор.Таким образом, Linq-to-db приведенного выше кода, он просто переводит вещи в: WHERE CountryId = 1.

Принимая во внимание, что если мы с нетерпением извлекаем объекты в память, мыможет вывести поведение легче.Это не приводит к появлению строк, даже если мы копируем все свойства, так как cx указывает на другой адрес.Итак, этот Linq-в-памяти не производит никаких строк:

foreach (var c in s.Query<Country>())
{
    Console.WriteLine("\n{0}'s people", c.CountryName);

    var cx = new Country
    {
         CountryId = c.CountryId,
         CountryName = c.CountryName,
         People = c.People.ToArray().ToList(),
         Population = c.Population
    };

    foreach(var p in s.Query<Person>().Fetch(x => x.Country)
                      .ToList().Where(x => x.Country == cx) )
    {
        Console.WriteLine("{0}", p.PersonName);
    }

}

Вот еще один Linq-в-памяти код, на этот раз он производит строки,следовательно, мы можем заключить, что интернированные объекты NHibernate.

var china = s.Get<Country>(1);
china.Population = 777;

foreach (var c in s.Query<Country>())
{
    Console.WriteLine("\n{0}'s people", c.CountryName);

    foreach(var p in s.Query<Person>().Fetch(x => x.Country)
                      .ToList().Where(x => x.Country == china) )
    {   
        Console.WriteLine("{0} {1}", p.PersonName, p.Country.Population);
    }
}

Помимо приведенного выше кода, создает строки, еще одно доказательство того, что Китай страны имеет ту же ячейку памяти, что и Country's Person: Person.Country.Population, также выводит 777.

Итак, я могу заключить, что NHibernate также использует интернирование объектов (в плане реализации, я думаю, что NH реализует вещи эффективно, ему не нужно сравнивать все свойства, когда он решает интернировать объекты, он может использоватьID как механизм, что думаете? : -) )

0 голосов
/ 28 мая 2011

Не могу сказать наверняка для NHibernate, но если он следует тем же правилам, что и Hibernate (как я подозреваю), он гарантирует, что в данном сеансе у вас может быть только один экземпляр данного объекта для данного ID.Это означает, что если экземпляр Country уже загружен в сеансе и если у страны человека есть ID этого загруженного экземпляра, страна и страна этого человека будут одним и тем же экземпляром, что вполне логично.

сеанс является кешем, и в этом кеше есть только один экземпляр объекта с заданным идентификатором.Нет необходимости перегрузки оператора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...