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