2013-11-15 5 views
16

Profilato con SQL Server Profiler: EF 6 esegue ogni singola chiamata di stored procedure con BEGIN TRAN e COMMIT TRAN.EF6 esegue il wrapping di ogni singola chiamata di stored procedure nella propria transazione. Come prevenire questo?

Non è un cambio di rottura?

Forse non è solo un cambiamento di rottura, ma rende qualsiasi logica transazionale impossibile in SP come abbiamo mai in grado di far ritirare la nostra transazione nella stored procedure utilizzando ROLLBACK TRAN (nota: non ci sono le transazioni nidificate in SQL Server), in modo da un rollback rollback a @@TRANCOUNT zero. Dato che eravamo in una transazione perché EF 6 abbiamo ottenuto "Conteggio transazioni dopo EXECUTE indica un numero non corrispondente di istruzioni BEGIN e COMMIT. Conteggio precedente = 1, conteggio corrente = 0". errore standard di SQL Server.

Per favore non chiedermi perché voglio chiamare stored procedure. Ne ho centinaia e tutti usano la logica TRY ... COMMIT ... CATCH ROLLBACK.

Qualche idea come posso impedire a EF 6 di farlo?

+0

Informazioni sull'utilizzo di ['UseTransaction'] (http://msdn.microsoft.com/en-us/library/system.data.entity.database.usetransaction (v = vs.113) .aspx) e avvio del proprio manualmente? –

+0

Cosa ne pensi di utilizzare direttamente ADO.Net se vuoi un maggiore controllo? – Aron

risposta

23

di sovraccarico del metodo ExecuteSqlCommand che impedisce questo comportamento:

db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sql, parameters); 
+0

Grazie, Max sei fantastico :-). È interessante notare che i guru EF hanno ignorato questa domanda per più di 2 mesi. (e ignorato il fatto che si tratta di un cambio di rottura) –

+0

Informazioni salvavita: sono state cercate per settimane! Grazie! – eghetto

15

In EF 6.1.2, un flag controlla il comportamento. L'impostazione di ConfirmTransactionsForFunctionsAndCommands influisce su SP che sono stati importati in un'entità (questi chiamano ExecuteFunction() internamente).

using (SomeEf6Context ctx = NewContext()) 
{ 
    ctx.Configuration.EnsureTransactionsForFunctionsAndCommands = false; 
    // Call an imported SP 
}  

L'impostazione non ha effetto sulle chiamate di SaveChanges().

MSDN Link

+0

È importante sottolineare che questa correzione richiede un aggiornamento di EF 6.1.2 o più recente. Stavo correndo intorno chiedendomi perché non riuscivo a trovare la proprietà GuaranteTransactionsForFunctionsAndCommands per quasi una settimana perché stavo usando EF 6.0.0. – Zachary

0

Come quello che crokusek Detto questo, è possibile impostare quella bandiera per disabilitare le operazioni per la SP.

Se si utilizza qualsiasi Dependency Injection (DI) biblioteca, è possibile impostare che come questo (sto usando iniettore semplice):

public partial class Startup 
{ 
    public Container ConfigureSimpleInjector(IAppBuilder app) 
    { 
     var container = new Container(); 

     // Configure OWIN and Identity Framework 
     ... 

     // Configure persistence 
     container.RegisterPerWebRequest<FakeDbContext>(() => 
     { 
      var fakeDbContext = new FakeDbContext(); 
      fakeDbContext.Configuration.EnsureTransactionsForFunctionsAndCommands = false; 
      return fakeDbContext; 
     } 

     // Register other services 
     ... 

     container.Verify(); 

     // For MVC 
     DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container)); 

     return container; 
    } 
} 
0

Solo per contribuire, sto utilizzando Unity come DI, EF 6.1.3 e prima il database e ricevevo il messaggio: "La nuova transazione non è consentita perché ci sono altri thread in esecuzione nella sessione" quando ho chiamato una procedura o una funzione mappata nel mio file edmx. L'opzione ConfirmTransactionsForFunctionsAndCommands = false ha risolto il problema. Anche la soluzione di Max Zerbini funzionava, ma dovrei usare in questo modo per ogni chiamata di procedura.

Problemi correlati