Tenho vindo a investigar transações e parece que eles cuidar de si na EF, enquanto eu passar false
para SaveChanges()
e, em seguida, chamar AcceptAllChanges()
se não há erros:
SaveChanges(false);
// ...
AcceptAllChanges();
E se algo der errado? não preciso reverter ou, assim que meu método estiver fora do escopo, a transação será encerrada?
O que acontece com qualquer coluna de identificação que tenha sido atribuída na metade da transação? Presumo que se alguém adicionou um registro após o meu antes que o meu ficasse ruim, isso significa que haverá um valor de identidade ausente.
Existe algum motivo para usar a TransactionScope
classe padrão no meu código?
c#
entity-framework
transactions
Mark Smith
fonte
fonte
SaveChanges(fase); ... AcceptAllChanges();
havia um padrão em primeiro lugar. Observe como a resposta aceita para a pergunta acima é escrita pelo autor de um blog - e esse blog é referenciado na outra pergunta. Tudo vem junto.Respostas:
Com o Entity Framework, a maior parte do tempo
SaveChanges()
é suficiente. Isso cria uma transação ou inscreve-se em qualquer transação ambiental e faz todo o trabalho necessário nessa transação.Às vezes, embora o
SaveChanges(false) + AcceptAllChanges()
emparelhamento seja útil.O local mais útil para isso é em situações nas quais você deseja fazer uma transação distribuída em dois contextos diferentes.
Ou seja, algo assim (ruim):
Se
context1.SaveChanges()
for bem-sucedido, mascontext2.SaveChanges()
falhar, toda a transação distribuída é abortada. Infelizmente, porém, o Entity Framework já descartou as alteraçõescontext1
, portanto você não pode reproduzir ou registrar efetivamente a falha.Mas se você alterar seu código para ficar assim:
Enquanto a chamada
SaveChanges(false)
envia os comandos necessários para o banco de dados, o contexto em si não é alterado; portanto, você pode fazê-lo novamente, se necessário, ou pode interrogar oObjectStateManager
que desejar.Isso significa que, se a transação realmente lançar uma exceção, você poderá compensar, tentando novamente ou registrando o estado de cada contexto
ObjectStateManager
algum lugar.Veja meu blog para mais.
fonte
SaveChanges(false)
faz a atualização real no banco de dados, enquantoAcceptAllChanges()
informa à EF: "Ok, você pode esquecer quais coisas precisam ser salvas, porque elas foram salvas com êxito". SeSaveChanges(false)
falhar,AcceptAllChanges()
nunca será chamado e o EF ainda considerará seu objeto como tendo propriedades que foram alteradas e precisam ser salvas novamente no banco de dados.Se você estiver usando EF6 (Entity Framework 6+), isso foi alterado para chamadas de banco de dados para SQL.
Consulte: http://msdn.microsoft.com/en-us/data/dn456843.aspx
use context.Database.BeginTransaction.
Do MSDN:
fonte
throw;
ao snippet do MSDN e indiquei claramente que não é o original do artigo do MSDN.Rollback()
é chamado caso esteja falando com o MySql ou algo que não tenha esse comportamento automático.Como algum banco de dados pode lançar uma exceção em dbContextTransaction.Commit (), é melhor que isso:
fonte
false
entracontext.SaveChanges();
e liga adicionalmentecontext.AcceptAllChanges();
.