Why thi开发者_如何学Pythons code works?
Does NHibernate employ object-interning?
If not, the following works because NHibernate overload Equals operator?
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);
}
I guess one can get a "false" conclusion that Hibernate is employing object interning if using Linq. As this is working too(i.e. produces rows):
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);
}
The Linq-to-db provider of NHibernate doesn't care for the entity's other fields when comparing objects(actually, things are compared on DB-level, not objects), it compares id only. So the Linq-to-db of above code, it merely translate things to: WHERE CountryId = 1.
Whereas if we eagerly fetch objects to memory, we can infer behaviors more easily. This doesn't produce any rows, even we copy all properties, as cx is pointing at different address. So this Linq-to-memory doesn't produce any rows:
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);
}
}
Here's another Linq-to-memory code, this time it produces rows, hence we can conclude that NHibernate interns objects.
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);
}
}
Aside from the above code produces rows, another proof that the Country china shares the same memory location with Person's Country: Person.Country.Population outputs 777 too.
So I guess, I can conclude that NHibernate employs object interning too(implementation-wise, I think NH implement things efficiently, it doesn't need to compare all properties when it decide to intern objects, it can use ID as a mechanism, whatdya think? :-) )
Can't tell for NHibernate for sure, but if it follows the same rules as Hibernate (as I suspect), it guarantees that in a given session, you may only have one instance of a given entity for a given ID. This means that if a Country instance is already loaded in the session and if a person's country has the ID of this loaded instance, the country and the person's country will be the same instance, which is quite logical.
The session is a cache, and there is only one instance of an entity with a given ID in this cache. No need for operator overloading.
精彩评论