35

使用 SQL Server Profiler 进行分析:EF 6 使用BEGIN TRAN和包装每个存储过程调用COMMIT TRAN

这不是一个突破性的变化吗?

也许这不仅是一项重大更改,而且使 SP 中的任何事务逻辑都变得不可能,因为我们永远无法使用存储过程回滚我们的事务ROLLBACK TRAN(注意:SQL Server 中没有嵌套事务),因此一个回滚回滚@@TRANCOUNT为零。因为我们在事务中,因为 EF 6 我们得到“EXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。以前的计数 = 1,当前计数 = 0。” 标准 SQL Server 错误。

请不要问我为什么要调用存储过程。我有数百个,他们都在使用TRY ... COMMIT ... CATCH ROLLBACK逻辑。

有什么想法可以防止 EF 6 这样做吗?

4

4 回答 4

39

有一个ExecuteSqlCommand方法的重载可以防止这种行为:

db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sql, parameters);
于 2014-01-27T15:10:56.903 回答
30

在 EF 6.1.2 中,标志控制行为。将EnsureTransactionsForFunctionsAndCommands设置为 false 将影响已导入实体的 SP(这些在内部调用 ExecuteFunction())。

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

该设置不会影响任何 SaveChanges() 调用。

MSDN 链接

于 2015-04-14T19:14:59.123 回答
0

正如 crokusek 所说,您可以设置该标志以禁用 SP 的交易。

如果您使用任何依赖注入 (DI) 库,您可以这样设置(我使用的是 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;
     }
}
于 2015-11-20T19:38:41.047 回答
0

只是为了做出贡献,我首先将 Unity 用作 DI、EF 6.1.3 和数据库,当我调用过程或函数时,我收到消息: “不允许新事务,因为会话中还有其他线程正在运行”映射到我的 edmx 文件中。选项EnsureTransactionsForFunctionsAndCommands = false解决了这个问题。Max Zerbini 的解决方案也有效,但我必须对每个过程调用使用这种方式。

于 2016-10-24T13:57:32.990 回答