Pergunta

Uma das coisas que me completamente confuso é o uso de session.Flush,em conjunto com session.Commit, e session.Close.

Às vezes session.Close funciona, por exemplo, ele compromete-se a todas as mudanças que eu preciso.Eu sei que eu preciso para usar cometer quando eu tiver uma transação, ou uma unidade de trabalho com vários cria/updates/deletes, para que eu possa escolher a reversão se um erro ocorre.

Mas às vezes eu fico realmente intrigado pela lógica atrás session.Flush.Tenho visto exemplos de onde você tem uma session.SaveOrUpdate() seguido por um flush, mas quando eu remover o autoclismo funciona bem assim mesmo.Às vezes eu me deparo com erros no Flush declaração dizendo que a sessão expirou, e removê-lo a certeza de que não corri em que erro.

Alguém tem uma boa orientação de como e onde ou quando usar um Flush?Eu verifiquei o NHibernate documentação para isso, mas eu ainda não consigo encontrar uma resposta direta.

Foi útil?

Solução

Brevemente:

  1. Sempre utilize as transações
  2. Não use Close(), em vez quebrar suas chamadas em uma ISession dentro de um using instrução ou gerenciar o ciclo de vida do seu ISession em outro lugar.

A partir de a documentação:

De vez em quando ISession irá executar as instruções SQL necessárias para sincronizar o ADO.NET estado de conexão com o estado de objetos mantidos na memória.Este processo, flush, ocorre, por padrão, nos seguintes pontos

  • a partir de algumas invocações de Find() ou Enumerable()
  • a partir de NHibernate.ITransaction.Commit()
  • a partir de ISession.Flush()

As instruções SQL são emitidos na seguinte ordem

  1. todas as inserções de entidade, na mesma ordem que os objetos correspondentes foram salvos usando ISession.Save()
  2. todas as atualizações de entidades
  3. todas as deleções de coleções
  4. todos os elementos de coleção exclusões, atualizações e inserções
  5. todas as inserções de coleção
  6. todas as deleções de entidade, na mesma ordem que os objetos correspondentes foram excluídos usando ISession.Delete()

(Uma exceção é que os objetos usando o nativo de geração de ID são inseridos quando eles são salvos.)

Excepto quando explicitamente Flush(), não há absolutamente nenhuma garantia sobre quando a Sessão executa o ADO.NET chamadas, apenas a ordem em que eles são executados.No entanto, o NHibernate não garante que o ISession.Find(..) métodos nunca irá retornar dados obsoletos;nem retornam os dados errados.

É possível alterar o comportamento padrão para um flush ocorre com menos freqüência.O FlushMode classe define três modos diferentes:só lave no tempo de confirmação (e apenas quando o NHibernate ITransaction A API é usada), lave automaticamente usando o explicado rotina, ou nunca lave a menos que Flush() é chamado explicitamente.O último modo é útil por muito tempo a executar as unidades de trabalho, onde um ISession é mantido aberto e desligado por um longo tempo.

...

Consulte também esta seção:

Terminar uma sessão envolve quatro fases distintas:

  • esvaziar a sessão
  • confirmar a transação
  • fechar a sessão
  • tratar exceções

Liberação da Sessão

Se acontecer de você estar usando o ITransaction API, você não precisa se preocupar com esta etapa.Será realizada implicitamente quando a transação é confirmada.Caso contrário, você deve chamar ISession.Flush() para garantir que todas as alterações são sincronizadas com o banco de dados.

Cometer a transação de banco de dados

Se você estiver usando o NHibernate Transaction API, esta aparência:

tx.Commit(); // flush the session and commit the transaction

Se você estiver gerenciando ADO.NET transações de si mesmo, você deve manualmente Commit() o ADO.NET transação.

sess.Flush();
currentTransaction.Commit();

Se você decidir não confirmar as alterações:

tx.Rollback();  // rollback the transaction

ou:

currentTransaction.Rollback();

Se você reverter a transação deve ser fechado imediatamente e descartar a sessão atual para garantir que o NHibernate interna do estado é consistente.

Fechar a ISession

Uma chamada para ISession.Close() marca o fim de uma sessão.A principal implicação do Close() é que a ADO.NET conexão será abandonada pela sessão.

tx.Commit();
sess.Close();

sess.Flush();
currentTransaction.Commit();
sess.Close();

Se você forneceu sua própria conexão, Close() retorna uma referência para ele, então você pode fechá-lo manualmente ou devolvê-lo para a piscina.Caso contrário, Close() retorna para a piscina.

Outras dicas

Começando no NHibernate 2.0, as transações são necessários para DB operações.Por conseguinte, o ITransaction.Commit() chamada irá lidar com qualquer necessárias rubor.Se, por alguma razão, você não estiver usando o NHibernate transações, então não haverá auto-nivelamento da sessão.

De vez em quando o ISession irá executar as instruções SQL necessárias para sincronizar o ADO.NET estado de conexão com o estado de objetos mantidos na memória.

E use sempre

 using (var transaction = session.BeginTransaction())
 {
     transaction.Commit();
 }

depois que as alterações são confirmadas do que isso muda para guardar em banco de dados vamos utilizar a transação.Commit();

Aqui estão dois exemplos de código onde não sem a sessão.Flush():

http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html

no final deste processo, você pode ver uma seção de código onde eu definir a identidade inserir, salvar a entidade, em seguida, esvaziar, em seguida, definir a identidade inserir fora.Sem esta liberação parecia ser a definição de identidade inserir e, em seguida, guardar a entidade.

O uso de Flush() me deu mais controle sobre o que estava acontecendo.

Aqui está outro exemplo:

Enviar NServiceBus mensagem dentro do escopo de transação

Eu não entendemos o porquê, mas o Flush() impediram o meu erro aconteça.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top