NHibernate是否使用对象实习?

时间:2011-05-28 08:05:48

标签: hibernate nhibernate architecture

为什么这段代码有效?

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 :(得分:0)

无法确定NHibernate,但是如果它遵循与Hibernate相同的规则(我怀疑),它保证在给定的会话中,您可能只有给定ID的给定实体的一个实例。这意味着如果国家/地区实例已在会话中加载,并且某个人的国家/地区具有此已加载实例的ID,则该国家/地区和该国家/地区将是同一个实例,这非常符合逻辑。

会话是一个缓存,并且在此缓存中只有一个具有给定ID的实体实例。无需操作员重载。

答案 1 :(得分:0)

我想如果使用Linq,Hibernate正在使用对象实习,我可以得到一个“错误”的结论。因为这也有效(即产生行):

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);
}

NHibernate的Linq-to-db提供程序在比较对象时并不关心实体的其他字段(实际上,在数据库级别而不是对象上比较事物),它只比较id。所以上面代码的 Linq-to-db ,它只是将事物转换为: WHERE CountryId = 1.

然而,如果我们急切地将对象提取到内存,我们可以更容易地推断出行为。这不会产生任何行,即使我们复制所有属性,因为 cx 指向不同的地址。所以 Linq-to-memory 不会产生任何行:

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-to-memory 代码,这次它产生行,因此我们可以得出结论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 China与Person's Country共享相同的内存位置:Person.Country.Population也输出777。

所以我想,我可以得出结论NHibernate也使用对象实习(实现方面,我认为NH有效地实现了事情,它不需要在决定实习对象时比较所有属性,它可以使用ID作为什么机制,什么叫?: - )