2010-11-05 13 views
6

Todo el mundo sabe que hay caché en sesión. Este caché en general podrían ser aprobados por 2 métodos:NHibernate evict por id

  1. Session.Evict
  2. Session.clear

Segundo método elimina toda caché no sólo para la entrada individual.

Tengo un método de negocio. Recibe la identificación del objeto grande (del sitio aspx) o, a veces, varios identificadores. Y realice la operación sql nativa en la base de datos (usando sql-query con lógica compleja para no cargar todos los datos en C#). Entonces necesito invalidar el caché. Por lo tanto, cada carga potencial de un objeto no tiene caché directo desde la base de datos.

Desafortunadamente desalojo aceptar solo objetos. Además, su implementación DefaultEvictEventListener tiene una separación clara en la ruta del código, separada para proxy y no para las clases proxy. Intenté simplemente crear la entidad, completar el ID manualmente y pasarlo a Evict. Esto no funciona Como entiendo Expulsar por clase no proxy, use GetHashCode para encontrar y eliminar objetos de la memoria caché. Entonces, si no lo estoy anulando, no funcionará. Tengo muchas operaciones nativas de lotes sql, por lo que reemplazar todo GetHashcode en todos los objetos de entidades creará mucho trabajo. Además, no estoy seguro de que este caso elimine los proxies de la memoria caché o no. Actualización: Por lo que he intentado para mí sobreescribir GetHashCode tampoco me ayudó. StatefulPersistenceContext.RemoveEntry no se encontró la entidad porque usa RuntimeHelpers.GetHashCode. Por lo que esta solución no es posible incluso

El uso de fuentes de NHibernate He producido siguiente solución:

public static class NHSessionHelper: DefaultEvictEventListener 
public static void RemoveEntityFromCache(this ISession session, Type type, object entityId) 
    { 
     ISessionImplementor sessionImpl = session.GetSessionImplementation(); 
     IPersistenceContext persistenceContext = sessionImpl.PersistenceContext; 
     IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(type.FullName); 

     if (persister == null) 
     { 
      return; 
     } 

     EntityKey key = new EntityKey(entityId, persister, sessionImpl.EntityMode); 
     persistenceContext.RemoveProxy(key); 

     object entity = persistenceContext.RemoveEntity(key); 
     if (entity != null) 
     { 
      EntityEntry e = persistenceContext.RemoveEntry(entity); 
      DoEvict(entity, key, e.Persister, (IEventSource)sessionImpl); 
     } 
    } 

Simplemente utiliza parte de la implementación NHibenate. Pero me parece que no es buena idea duplicar el código. Puede ser que alguien tenga otras ideas?

Respuesta

9

Si está seguro de que el objeto está en la caché, Session.Get(id) no golpeará la base de datos. Es probable que sea más fácil de hacerlo y luego Evict el objeto que nos devuelve:

Model m = Session.Get(id); 
Session.Evict(m); 

Editar

No me queda claro si se está hablando acerca de la caché de primer nivel o el segundo nivel cache. Lo anterior desalojará algo de la memoria caché de primer nivel. Para expulsar del caché de segundo nivel, use el método de expulsión en SessionFactory.

Editar en respuesta al comentario

En ese caso, puede intentar Session.Load:

Model m = Session.Load(id); 
Session.Evict(m); 

Si m está en la caché, Session.Load devolverá el ejemplo que se puede expulsar. Si no, devuelve un proxy (sin hit db). Mis pruebas sugieren que Session.Evict no arrojará si intenta desalojar el proxy, por lo que debería funcionar.

+0

Esto es lo que hay que hacer.Obtener devuelve un proxy para el modelo y establece el id – jonnii

+0

Estoy hablando de caché de primer nivel. No estoy seguro si está en caché o no. A veces es a veces no. En cualquiera de estos casos, quiero borrarlo de la memoria caché. Si no está en la memoria caché, el código podría afectar realmente a la base de datos. Entonces quiero un código idéntico para ambos casos. Para que la operación de manipulación de datos solo se asegure de que no haya datos en la memoria caché. –

+0

En referencia al último "Editar en respuesta al comentario". Si no va a golpear la base de datos dentro de Desalojar al manipular y sin excepción para la entidad que no está en el caché, diría que su solución es la mejor. –

2

Parece que podría usar una sesión sin estado para esto y no molestarse con la caché.

+0

Estaba pensando en sesiones sin estado. Es una buena idea. Pero tengo demasiados códigos escritos (algo así como 152 métodos comerciales). Y si cambio todo a sesión sin estado. Voy a muchos códigos para probar. Al menos como todas las operaciones usarán el mismo tipo de sesión. Me parece que no es idea cuando algunos DAO usarán un tipo de sesison y otros usarán otro. –

+0

La idea básica es utilizar sesiones normales cuando va a navegar relaciones y actualizar los objetos persistentes, y sesiones sin estado cuando simplemente desea ejecutar una consulta y devolver un objeto POCO. –