2011-11-01 10 views
6

piszę projekt i przy użyciu NHibernate 3.1Dlaczego NHibernate rzucić "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) 
} 

Ostatnia zmiana rzuca wyjątek: zapytanie

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 jest poprawna. Może to jest współbieżność? Masz jakieś pomysły?

+0

@ManuPK, wyjątek jest zgłaszany na linii tx.Commit(); –

Odpowiedz

5

StaleObjectStateException to sposób hibernacji zapewniający spójność danych, przeczytaj API here. Hibernate utrzymuje version obiektów, które aktualizuje i spowoduje błąd, jeśli wersja w DB i w pamięci nie będą pasować. Przeczytaj więcej o optymistycznym mechanizmie blokowania here.

Tak, Debuguj aplikację z tymi informacjami. Nie jestem zaznajomiony ze składnią C#, ale myślę, że drugi zapis powinien być w stanie else.

+0

To prawda, całkowicie to przegapiłem: P +1. @Kovpaev - Usuń ostatnią 'session.SaveOrUpdate (entity)', nie ma takiej potrzeby. –

+0

@Ash Burlaczenko, wywołanie na końcu metody jest potrzebne, jeśli metoda Update() jest wywoływana w kontekście zewnętrznej transakcji. Jeśli nie, jest tworzony w bloku "jeśli". –

Powiązane problemy