Pregunta

Cuando uso Rhino Commons UnitOfWork (en una UnitOfWorkApplication para ASP-MVC), me gusta usar la clase estática Rhino Repository para guardar entidades como esta:

Repository<Car>.Save(new Car(Id = 1));

Encuentro que puedo sacar la entidad inmediatamente después de esa llamada usando:

Car car = Repository<Car>.Get(1);

Esto funciona bien. Sin embargo, cuando uso el proveedor NHibernate Linq en Rhino UnitOfWork de esta manera:

var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()
               select rep).ToList();

Me sale una lista vacía. Parece que tengo que llamar a UnitOfWork.Current.Flush () antes de poder sacar el auto de esta manera. No entiendo por qué, dado que detrás de escena supongo que ambos métodos de recuperación están consultando la misma sesión / unidad de trabajo. ¿Esto significa que debe llamar a UnitOfWork.Current.Flush () después de cada guardado en la base de datos? ¿No debería NHibernate ser capaz de resolver cuándo enjuagarse? ¿O estoy malinterpretando algo?

¿Fue útil?

Solución

Bien, parece que aunque una llamada Get al Repositorio puede usar el caché de sesión, también puede "ver" el auto guardado en el caché:

Car car = Repository<Car>.Get(1); // This works because it uses the same session

Una consulta linq NO utiliza el caché de sesión:

var allCars = (from rep in UnitOfWork.CurrentSession.Linq<Car>()               
select rep).ToList(); // Does not work, even if it is in the same code block and even though it uses the same session

La mejor práctica es que cualquier cambio en la base de datos (guardar, actualizar, eliminar, insertar) debe ir seguido de:

UnitOfWork.Session.Flush(), 

o envuelto en un:

With.Transaction(delegate{
   // code here
})

o decore su método con [Transacción] y use ATM. Esto garantizará que las consultas posteriores de linq busquen datos actualizados.

Otros consejos

Cuando llama a Repository.Save, está notificando a la sesión que el repositorio mantiene para rastrear ese objeto y sincronizar los cambios en la base de datos en el siguiente vaciado. Hasta que elimine la sesión, no se realizan cambios en la base de datos. Sin embargo, el objeto se convierte en parte de la memoria caché de la sesión, por lo que Get (1) lo devolverá.

Cuando ejecuta una consulta para completar una colección, la sesión consulta la base de datos para obtener los resultados, a menos que ya haya almacenado en caché esos resultados. Dado que aún no ha actualizado la base de datos, el automóvil que agregó a la sesión no formará parte del conjunto de resultados. (< - Posiblemente incorrecto) Si estoy leyendo la documentación correctamente, tanto los resultados de la consulta como las entidades editadas Save () deben agregarse al caché de sesión (primer nivel). Eso no significa necesariamente que el querystatement.List() consulta el caché después de agregar los resultados de la base de datos ... Me cuesta mucho entender exactamente qué está sucediendo.

Como comentario aparte, creo que puede configurar la sesión para que se elimine automáticamente, pero tendría que verificar la documentación.

ACTUALIZACIÓN:

Creo que podría ver lo que está pasando aquí. La sesión predeterminada FlushMode es Auto pero Rhino's UnitOfWork.Start() crea una sesión con un Commit establecido en Flush(), lo que significa que la sesión no se auto-vaciará a menos que llame explícitamente a FlushMode = Auto o confirme la transacción. Con un Session.Find de UnitOfWork.CurrentSession.FlushMode = FlushMode.Auto;, NHibernate (¿a veces?) Vaciará la sesión antes de consultar para evitar que se devuelvan datos obsoletos. Si estoy en lo cierto, su transacción de base de datos se parece a:

SELECT * FROM Car

INSERT INTO Car (...) VALUES (...)

Cuando el enjuague automático parece un poco ambiguo de la documentación / blogs que he leído ... la respuesta más común es que con <=> enjuaga & "; a veces &"; aunque garantiza que <=> nunca devolverá datos obsoletos. Dado que NHibernate Linq en realidad solo crea una consulta de Criterios, es posible que no active la descarga automática (tal vez esto se haya solucionado ahora ... es difícil saberlo).

Por lo tanto, me parece que en su caso desea eliminar después de su guardado porque desea recuperar de inmediato los resultados de su guardado. En una unidad de trabajo más pequeña donde solo estaba actualizando entidades, un solo Commit () estaría bien. Tal vez <=> haría el truco, pero el hecho de que la fábrica UOW establezca explícitamente el modo en Comprometer parece alentarlo a pensar realmente en sus límites UOW.

Gracias a Stuart Childs, sospecho que tiene razón en que el problema puede estar relacionado con el proveedor de NHibernate Linq. No estoy seguro de lo que hace detrás de escena, pero podría usar una sesión diferente, si es así, tiene sentido que tenga que vaciar el repositorio antes de que la consulta de Linq lo 'vea'. ¡Es hora de mirar el código fuente, pero me han dicho que me derretirá la cabeza tratando de entenderlo!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top