entity framework6事务回滚

用EF6你有一个新的交易,可以像这样使用:

using (var context = new PostEntityContainer()) { using (var dbcxtransaction = context.Database.BeginTransaction()) { try { PostInformation NewPost = new PostInformation() { PostId = 101, Content = "This is my first Post related to Entity Model", Title = "Transaction in EF 6 beta" }; context.Post_Details.Add(NewPost); context.SaveChanges(); PostAdditionalInformation PostInformation = new PostAdditionalInformation() { PostId = (101), PostName = "Working With Transaction in Entity Model 6 Beta Version" }; context.PostAddtional_Details.Add(PostInformation); context.SaveChanges(); dbcxtransaction.Commit(); } catch { dbcxtransaction.Rollback(); } } } 

当事物横向摆动时,实际上需要回滚吗? 我很好奇,因为提交描述说:“提交底层存储事务”。

而回滚描述说:“回滚底层存储事务”。

这让我很好奇,因为在我看来,如果不调用Commit,以前执行的命令将不会被存储(这对我来说是合乎逻辑的)。 但是,如果是这种情况,那么调用回滚函数的原因是什么? 在EF5中,我使用的TransactionScope没有一个回滚函数(只有一个Complete),这对我来说似乎是合乎逻辑的。 由于MS DTC的原因,我不能使用TransactionScope了,但我也不能像上面的例子(即我只需要提交)使用try catch。

您不需要手动调用Rollback ,因为您正在使用using语句。

DbContextTransaction.Dispose方法将在using块的最后被调用。 如果事务未成功提交(未调用或遇到exception),它将自动回滚事务。 以下是SqlInternalTransaction.Dispose方法的源代码(当使用SqlServer提供程序时, DbContextTransaction.Dispose将最终委托给它):

 private void Dispose(bool disposing) { // ... if (disposing && this._innerConnection != null) { this._disposing = true; this.Rollback(); } } 

你看,它检查_innerConnection是不是空,如果不是,回滚事务(如果提交, _innerConnection将为空)。 让我们看看Commit做什么:

 internal void Commit() { // Ignore many details here... this._innerConnection.ExecuteTransaction(...); if (!this.IsZombied && !this._innerConnection.IsYukonOrNewer) { // Zombie() method will set _innerConnection to null this.Zombie(); } else { this.ZombieParent(); } // Ignore many details here... } internal void Zombie() { this.ZombieParent(); SqlInternalConnection innerConnection = this._innerConnection; // Set the _innerConnection to null this._innerConnection = null; if (innerConnection != null) { innerConnection.DisconnectTransaction(this); } } 

只要你总是在EF上使用SQL Server,就不需要显式地使用catch来调用Rollback方法。 允许使用块自动回滚任何exception将始终工作。

但是,从Entity Framework的angular度考虑时,可以看到为什么所有示例都使用显式调用来回滚事务。 对于EF来说,数据库提供程序是任意的,可插入的,提供程序可以用MySQL或任何其他具有EF提供程序实现的数据库来replace。 因此,从EF的angular度来看,不能保证提供者会自动回滚已处理的事务,因为EF不知道数据库提供者的实现。

所以,作为一个最佳实践,EF文档build议您明确回滚 – 以防万一您将提供程序更改为不处理自动回滚的实现。

在我看来,任何写得好的写得好的提供者都会自动回滚这个处理中的事务,所以额外的努力用try-catch-rollback来包装使用块中的所有内容是一件小事。

  1. 既然你已经写了一个'use'块来实例化事务,你不需要明确地提到Rollback函数,因为在处置的时候它会自动回滚(除非它被提交)。
  2. 但是,如果你在没有使用块的情况下实例化它,在这种情况下,在发生exception(恰好在catch块)的情况下回滚事务是非常重要的,而且对于更健壮的代码也是一个空检查。 BeginTransaction的工作方式不同于事务范围(如果所有操作都成功完成,只需要一个完整的函数)。 相反,它类似于Sql事务的工作。