我想可以得到一个“假”的结论,即如果使用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);
}
比较对象时(实际上,事情是在DB-水平相比的NHibernate的LINQ到DB提供程序不关心实体的其他领域,不是对象),它只比较id。所以Linq到分贝以上代码,它只是东西翻译成: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);
}
}
除了上面的代码中的各行,即国家中国股与使用者的国家相同的内存位置再一次证明:Person.Country.Population输出777了。所以我猜,我可以得出结论,NHibernate采用对象interning(实现方式,我认为NH有效地实现的东西,它不需要比较所有的属性时,它决定实习对象,它可以使用ID作为一个机制,whatdya认为?:-))
来源
2011-05-28 10:36:58
Hao
您的答案提示我比较不同会话中的对象。即使这两个对象来自相同的ID,但它们处于不同的会话中,它们也不共享相同的内存。所以NHibernate可以在同一会话中实习对象,但不会在不同的会话中 – Hao 2011-05-28 10:41:51
这是预期的行为。会话应该表示与数据库相对较短的交互,与其他并发会话隔离。 – 2011-05-28 11:09:31
这基本上是正确的,只有一点修正:会话不是缓存:它是**身份映射**(请参阅http://martinfowler.com/eaaCatalog/identityMap。html) – 2011-05-28 14:59:23