NHibernate StatelessSession: sin caché de primer nivel
En la próxima release de NHibernate estará disponible esta feature portada desde Hibernate por Fabio Maulo, los que deseen usarla en este momento deben hacerlo desde el trunk.
Qué hace? IStatelessSession es la interfaz que debemos usar para conseguir sesiones de NHibernate que no posean caché de primer nivel. Debemos recordar que la caché de primer nivel en ISession es obligatoria y siempre la usamos cuando trabajamos con NHibernate. Trabajar sin ella era imposible hasta ahora.
Para que sirve? Especialmente hecho para realizar operaciones en masa contra la base de datos.
Miremos este código:
using (ISessionFactory sf = cfg.BuildSessionFactory()) { using (IStatelessSession session = sf.OpenStatelessSession()) { using (ITransaction tx = session.BeginTransaction()) { Foo f = new Foo(); f.Id = 1; f.Misc = "m1"; f.Name = "n1"; session.Insert(f); f.Id = 2; session.Insert(f); tx.Commit(); Debug.Assert(session.CreateQuery("from Foo") .List().Count == 2); } } }
Como verán el objeto f fué creado 1 vez y mandado a persistir dos veces con el Id cambiado, primero con ‘1′ y luego con ‘2′. En un escenario común con caché de primer nivel esto no funcionarÃa, ya que NHibernate “recordarÃa” al objeto f desde que fué guardado por primera vez. Y como resultado en la base habrán 2 objetos guardados.
Notese también que al guardar el objeto realizamos un Insert en vez de un Save. Las inferzaces ISession e IStatelessSession no se relacionan para nada.
Para que este ejemplo funcione con cache de primer nivel es obligatorio hacer que NHibernate se “olvide” del objeto que acabamos de guardar llamando al metodo Evit(object) -método no disponible en IStatelessSession como podrán intuir. Y se verÃa asÃ:
using (ISessionFactory sf = cfg.BuildSessionFactory()) { using (ISession session = sf.OpenSession()) { using (ITransaction tx = session.BeginTransaction()) { Foo f1 = new Foo(); f1.Id = 1; f1.Misc = "m1"; f1.Name = "n1"; session.Save(f1); //Eliminamos el objeto de la cache session.Evict(f1); f1.Id = 2; session.Save(f1); tx.Commit(); Debug.Assert(session. CreateQuery("from Foo").List().Count == 2); } } }
Recursos: