问题
Profiled with SQL Server Profiler: EF 6 wraps every single stored procedure call with BEGIN TRAN
and COMMIT TRAN
.
Is not it a breaking change?
Maybe it is not only a breaking change, but makes any transactional logic impossible in SPs as we never can rollback our transaction in the stored procedure using ROLLBACK TRAN
(note: there are no nested transactions in SQL Server), so one rollback rollbacks to @@TRANCOUNT
zero. As we were in a transaction because EF 6 we got "Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0." standard SQL Server error.
Please do not ask me why I want to call stored procedures. I have hundreds, and all of them are using TRY ... COMMIT ... CATCH ROLLBACK
logic.
Any ideas how can I prevent EF 6 to do this?
回答1:
There is an overload of the ExecuteSqlCommand
method that prevents this behavior:
db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sql, parameters);
回答2:
In EF 6.1.2, a flag controls the behavior. Setting EnsureTransactionsForFunctionsAndCommands to false will affect SPs that have been imported into an entity (these call ExecuteFunction() internally).
using (SomeEf6Context ctx = NewContext())
{
ctx.Configuration.EnsureTransactionsForFunctionsAndCommands = false;
// Call an imported SP
}
The setting will not affect any SaveChanges() calls.
MSDN Link
回答3:
As what crokusek said, you can set that flag to disable transactions for SPs.
If you are using any Dependency Injection (DI) library, you can set that like this(I am using Simple Injector):
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;
}
}
回答4:
Just to contribute, I'm using Unity as DI, EF 6.1.3 and database first and I was getting the message: "New transaction is not allowed because there are other threads running in the session" when I called a procedure or a function mapped in my edmx file. The option EnsureTransactionsForFunctionsAndCommands = false fixed the problem. The Max Zerbini's solution worked too, but I would've to use that way for each procedure call.
来源:https://stackoverflow.com/questions/19991609/ef6-wraps-every-single-stored-procedure-call-in-its-own-transaction-how-to-prev