NHibernate não jogando StaleObjectStateException quando usado e os dados alterados no banco de dados
-
22-07-2019 - |
Pergunta
Eu tenho uma entidade mapeada em NHibernate com controle de concorrência otimista usando uma coluna SQL timestamp como o número da versão. O mapeamento é como o seguinte:
<class name="Entity" optimistic-lock="version" discriminator-value="0">
<id name="id">
<generator class="native" />
</id>
<version name="Version" column="Version" generated="always" unsaved-value="null" type="System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
...
<subclass name="ChildEntity" discriminator-value="1" />
</class>
Estou testando o que acontece quando os dados em uma fila nas mudanças de banco de dados entre o get ea atualização do registro. Para fazê-lo, estou executando uma instrução de atualização diretamente contra um dos registros na tabela que estão em vias de ser atualizado por NHibernate. Esta atualização direta muda o número da versão do registro na tabela.
Como esperado, a atualização NHibernate conseguiu não ocorre na linha específica (isso é bom). No entanto, nenhuma exceção é lançada durante a cometer. Eu esperava um StaleObjectStateException a ocorrer quando a transação foi confirmada para que eu pudesse reverter a transação e informar o usuário. Não é este o comportamento esperado? Estou faltando alguma coisa?
Meu código para confirmar a transação é algo como isto:
_session.BeginTransaction();
...
// load objects in session
IList<ChildEntity> toChange = _session.Find('some condition');
foreach ( var itemToChange in toChange )
{
itemToChange.Status = Status.Updated;
}
...
_session.Transaction.Commit();
Os itens pertencem à mesma sessão e todo o trabalho é concluído dentro de uma única transação. ChildEntity é uma subclasse da classe base Entity, que tem o definido para a versão optimistic-lock.
Solução 2
Parece que o meu teste foi impreciso. No teste, eu estava fazendo a começar depois a outra transação atualizou o registro. Esta outra atualização feita a inelegível linha para a atualização, por isso não atualização foi tentada. Quando eu mudei o teste para fazer a atualização competindo DEPOIS do Get, em seguida, o StaleObjectStateException foi lançada como esperado.
Desculpe pela confusão.
Outras dicas
Como você está modificando os dados? O StaleObjectException é lançada apenas quando tentativas NHibernate para atualizar a linha eo número da versão não é mais o mesmo. As outras colunas são irrelevantes. É possível que em sua testando você não está atualizando o número da versão?
A premissa é esta:
A. Usuário A & B obter objeto de banco de dados com versão = 1
SQL: SELECT [object] FROM [TABLE] where id = [id] and Version = 1
B. Um usuário do Updates objeto que muda a versão de 2
SQL: UPDATE [TABLE] SET [object] (& Set Version = 2) where id = [id] and Version = 1
retorna 1 linha atualizada
C. Usuário B tentativas para objeto de atualização, mas fica StaleObjectException como objeto de atualização com a versão = 1 (a versão que ele conseguiu passo 1) atualiza 0 registros no banco de dados.
SQL:. UPDATE [TABLE] SET [object] where id = [id] and Version = 1
retorna 0 linhas atualizado e StaleObjectException jogado