NHibernate Pitfalls: Entity Refresh
This is part of a series of posts about NHibernate Pitfalls. See the entire collection here.
Whenever an entity is loaded from NHibernate, either by its direct id, by LINQ, Criteria API, Query Over or HQL, it is stored in the first level cache. After that, whenever the row that this entity refers to is loaded by a query, the same entity is returned exactly as it is, that is, any eventual DB updates are ignored.
The only way to get DB updates to the loaded entity is to call Refresh, Lock or Merge, but you can also get current individual column values if you select them explicitly.
1: //entity is loaded into first level cache
2: var c1 = session.Get<Customer>(CustomerId);
3:
4: //same entity is returned
5: var c2 = session.Query<Customer>().Where(x => x.Id == CustomerId).Single();
6: Debug.Assert(Object.ReferenceEquals(c1, c2));
7:
8: var c3 = session.CreateQuery("from Customer c where c.Id = :id").SetParameter("id", CustomerId).UniqueResult<Customer>();
9: Debug.Assert(Object.ReferenceEquals(c1, c3));
10:
11: var c4 = session.CreateCriteria<Customer>().Add(NHibernate.Criterion.Expression.IdEq(CustomerId)).UniqueResult<Customer>();
12: Debug.Assert(Object.ReferenceEquals(c1, c4));
13:
14: var c5 = session.QueryOver<Customer>().Where(x => x.Id == CustomerId).SingleOrDefault();
15: Debug.Assert(Object.ReferenceEquals(c1, c5));
16:
17: //get updates from the DB
18: session.Refresh(c1);
19:
20: //get the current value from the DB
21: var n2 = session.Query<Customer>().Where(x => x.Id == CustomerId).Select(x => x.Name).Single();
22:
23: var n3 = session.CreateQuery("select Name from Customer c where c.Id = :id").SetParameter("id", CustomerId).UniqueResult().ToString();
24:
25: var n4 = session.CreateCriteria<Customer>().Add(NHibernate.Criterion.Expression.IdEq(CustomerId)).SetProjection(NHibernate.Criterion.Projections.Property("Name")).UniqueResult<String>(); ;
26:
27: var n5 = session.QueryOver<Customer>().Where(x => x.Id == CustomerId).Select(x => x.Name).SingleOrDefault<String>();