EF6 wraps every single stored procedure call in its own transaction. How to prevent this?

巧了我就是萌 提交于 2019-12-29 19:22:11

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!