Here's the common code:
namespace TestTheSecondLevelCache
{
public class Common
{
public static ISessionFactory BuildSessionFactory()
{
var sf = DomainMapping.Mapper.BuildSessionFactory();
using (var session = sf.OpenStatelessSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Stateless update");
var p = session.Get<Person>(1);
p.FirstName = "John";
session.Update(p);
tx.Commit();
}
return sf;
}
}
}
Query caching:
[TestMethod]
public void Test_Query_Caching_Compare_This_To_Entity_Caching()
{
var sf = Common.BuildSessionFactory();
Action query = delegate
{
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Query 1");
var person = session.Query<Person>().Where(x => x.PersonId == 1).Cacheable().Single();
}
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Query 2");
var person = session.Query<Person>().Where(x => x.PersonId == 2).Cacheable().Single();
}
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Query 3");
var person = session.Query<Person>().Where(x => x.PersonId == 1).Cacheable().Single();
}
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Query 4");
var person = session.Query<Person>().Where(x => x.PersonId == 2).Cacheable().Single();
}
};
query();
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Update");
var p = session.Get<Person>(1);
p.FirstName = "ZX-" + p.FirstName;
session.Save(p);
tx.Commit();
}
query();
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Assert");
var p = session.Get<Person>(1);
Assert.AreEqual("ZX-John", p.FirstName);
}
}
Output:
Test Name: Test_Query_Caching_Compare_This_To_Entity_Caching
Test Outcome: Passed
Result StandardOutput:
Stateless update
NHibernate:
SELECT
person0_.PersonId as PersonId4_0_,
person0_.FirstName as FirstName4_0_,
person0_.LastName as LastName4_0_
FROM
Person person0_
WHERE
person0_.PersonId=@p0;
@p0 = 1 [Type: Int32 (0)]
Query 1
NHibernate:
select
person0_.PersonId as PersonId4_,
person0_.FirstName as FirstName4_,
person0_.LastName as LastName4_
from
Person person0_
where
person0_.PersonId=@p0;
@p0 = 1 [Type: Int32 (0)]
Query 2
NHibernate:
select
person0_.PersonId as PersonId4_,
person0_.FirstName as FirstName4_,
person0_.LastName as LastName4_
from
Person person0_
where
person0_.PersonId=@p0;
@p0 = 2 [Type: Int32 (0)]
Query 3
Query 4
Update
Query 1
NHibernate:
select
person0_.PersonId as PersonId4_,
person0_.FirstName as FirstName4_,
person0_.LastName as LastName4_
from
Person person0_
where
person0_.PersonId=@p0;
@p0 = 1 [Type: Int32 (0)]
Query 2
NHibernate:
select
person0_.PersonId as PersonId4_,
person0_.FirstName as FirstName4_,
person0_.LastName as LastName4_
from
Person person0_
where
person0_.PersonId=@p0;
@p0 = 2 [Type: Int32 (0)]
Query 3
Query 4
Assert
As you can see, the query cache always gets evicted when there's a change on any of the row. Hence, even we didn't update person #2, all cached query on person gets evicted, resulting to re-fetching them from database. Not efficient
Contrast that query caching with entity caching, notice the use of Get:
[TestMethod]
public void Test_Entity_Caching_Compare_This_To_Query_Caching()
{
var sf = Common.BuildSessionFactory();
Action query = delegate
{
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Query 1");
var person = session.Get<Person>(1);
}
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Query 2");
var person = session.Get<Person>(2);
}
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Query 3");
var person = session.Get<Person>(1);
}
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Query 4");
var person = session.Get<Person>(2);
}
};
query();
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Update");
var p = session.Get<Person>(1);
p.FirstName = "ZX-" + p.FirstName;
session.Save(p);
tx.Commit();
}
query();
using (var session = sf.OpenSession())
using (var tx = session.BeginTransaction())
{
Console.WriteLine("Assert");
var p = session.Get<Person>(1);
Assert.AreEqual("ZX-John", p.FirstName);
}
}
Output:
Test Name: Test_Entity_Caching_Compare_This_To_Query_Caching
Test Outcome: Passed
Result StandardOutput:
Stateless update
NHibernate:
SELECT
person0_.PersonId as PersonId4_0_,
person0_.FirstName as FirstName4_0_,
person0_.LastName as LastName4_0_
FROM
Person person0_
WHERE
person0_.PersonId=@p0;
@p0 = 1 [Type: Int32 (0)]
Query 1
NHibernate:
SELECT
person0_.PersonId as PersonId4_0_,
person0_.FirstName as FirstName4_0_,
person0_.LastName as LastName4_0_
FROM
Person person0_
WHERE
person0_.PersonId=@p0;
@p0 = 1 [Type: Int32 (0)]
Query 2
NHibernate:
SELECT
person0_.PersonId as PersonId4_0_,
person0_.FirstName as FirstName4_0_,
person0_.LastName as LastName4_0_
FROM
Person person0_
WHERE
person0_.PersonId=@p0;
@p0 = 2 [Type: Int32 (0)]
Query 3
Query 4
Update
Query 1
Query 2
Query 3
Query 4
Assert
It's more efficient, both entity 1 and 2 are not re-fetched from DB even there's a change on entity
Happy Coding!
No comments:
Post a Comment