使用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,就不会存储以前执行的命令(这对我来说似乎合情合理)。但如果是这种情况,那么调用Rollback函数的原因是什么?在EF5中,我使用了TransactionScope,它没有回滚功能(只有一个完整的),这对我来说似乎是合乎逻辑的。由于MS DTC原因,我不能再使用TransactionScope,但我也不能像上面的例子一样使用try catch(即,我只需要提交)。
答案 0 :(得分:105)
您无需手动调用Rollback
,因为您使用的是using
语句。
DbContextTransaction.Dispose
方法将在using
块的末尾调用。如果事务未成功提交(未调用或遇到异常),它将自动回滚事务。以下是SqlInternalTransaction.Dispose
方法的源代码(DbContextTransaction.Dispose
在使用SqlServer提供程序时最终会委托给它):
private void Dispose(bool disposing)
{
// ...
if (disposing && this._innerConnection != null)
{
this._disposing = true;
this.Rollback();
}
}
你看,它检查_innerConnection
是否为空,如果没有,则回滚事务(如果已提交,_innerConnection
将为null)。让我们看看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);
}
}
答案 1 :(得分:21)
只要您始终使用带有EF的SQL Server,就不需要显式使用catch来调用Rollback方法。允许using块自动回滚任何异常将始终有效。
但是,当您从实体框架的角度考虑它时,您可以看到为什么所有示例都使用显式调用来回滚事务。对于EF,数据库提供程序是任意且可插入的,并且可以用MySQL或具有EF提供程序实现的任何其他数据库替换提供程序。因此,从EF的角度来看,不能保证提供者会自动回滚已处理的事务,因为EF不知道数据库提供者的实现。
因此,作为最佳实践,EF文档建议您显式回滚 - 以防万一有一天您将提供程序更改为不会自动回滚处置的实现。
在我看来,任何优秀且编写良好的提供程序都会自动回滚dispose中的事务,因此使用try-catch-rollback将所有内容包装在using块中的额外工作是过度的。
答案 2 :(得分:4)