2011-11-01 18 views
6

estoy escribiendo proyecto y el uso de NHibernate 3.1¿Por qué NHibernate lanza "StaleObjectStateException"?

SimpleTest:

Forum forum = Session.CreateCriteria<Forum>().Add(Restrictions.Eq("UrlName", "reportabug")).UniqueResult<Forum>(); 
forum.TopicsCount++; 
IForumRepository forumRepository = new ForumRepository(SessionFactory); 
forumRepository.Update(forum); 

public virtual void Update(TEntity entity) 
{ 
    if (!session.Transaction.IsActive) 
    { 
     TResult result; 
     using (var tx = session.BeginTransaction()) 
     { 
      session.SaveOrUpdate(entity) 
      tx.Commit(); 
     } 
     return result; 
    } 
    session.SaveOrUpdate(entity) 
} 

La última actualización lanza una excepción: consulta

StaleObjectStateException was unhandled by user code: 
    Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) 

SQL:

UPDATE Forums 
SET Name = 'Forums Issues (not product support)' /* @p0 */, 
     UrlName = 'reportabug' /* @p1 */, 
     Description = 'Use this forum to report issues with the online forums application. When reporting an issue please include relevant details such as repro steps, error messages and browser version.' /* @p2 */, 
     CategoryId = 'b2cc232c-0d5c-4f35-bb6f-29c67d7d40c2' /* @p3 */, 
     TopicsCount = 1 /* @p4 */ 
WHERE ForumId = '864046b7-ca57-48c4-8a81-082103223527' /* @p5 */ 

ForumID es correcta. Quizás esto sea concurrencia? ¿Alguna idea?

+0

@ManuPK, la excepción se produce en la línea tx.Commit(); –

Respuesta

5

StaleObjectStateException es una forma de hibernación que garantiza la coherencia de los datos, lea la API here. Hibernate mantiene el version de los objetos que actualiza y emitirá un error si la versión en DB y en memoria no coincide. Lea más sobre el mecanismo de bloqueo optimista here.

Por lo tanto, elimine la aplicación con esta información. No estoy familiarizado con la sintaxis C# pero creo que el segundo guardado debe estar en la condición else.

+0

Eso es correcto, lo extrañé por completo: P +1. @Kovpaev - Elimina la última 'session.SaveOrUpdate (entidad)', no es necesario. –

+0

@Ash Burlaczenko, se necesita una llamada al final del método si se invoca el método Update() en el contexto de la transacción externa. Si no, se crea en el bloque "si". –

Cuestiones relacionadas