[英]Entity Framework 6 transaction rollback
With EF6 you have a new transaction which can be used like: 使用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();
}
}
}
Is rollback actually needed when things go sideways? 当事情横盘整理时,是否真的需要回滚? I'm curious because the Commit description says: "Commits the underlying store transaction."
我很好奇,因为“提交”说明中说:“提交基础商店交易。”
Whereas the Rollback description says: "Rolls back the underlying store transaction." 而“回滚”说明说:“回滚基础商店交易。”
This makes me curious, because it looks to me that if Commit isn't called, the previously executed commands will not be stored (which seems logical to me). 这让我感到好奇,因为在我看来,如果未调用Commit,先前执行的命令将不会被存储(对我来说这是合乎逻辑的)。 But if that is the case, what would the reason be to call the Rollback function?
但是如果是这种情况,调用Rollback函数的原因是什么? In EF5 I used TransactionScope which didn't have a Rollback function (only a Complete) which seemed logical to me.
在EF5中,我使用了TransactionScope,它没有回滚功能(只有完整功能),这对我来说似乎很合理。 Due to MS DTC reasons I cannot use the TransactionScope anymore, but I also cannot use a try catch like the example above (ie, I only need the Commit).
由于MS DTC的原因,我不能再使用TransactionScope,但是也不能像上面的示例那样使用try catch(即,我只需要Commit)。
You don't need to call Rollback
manually because you are using the using
statement. 您不需要手动调用
Rollback
,因为您正在使用using
语句。
DbContextTransaction.Dispose
method will be called in the end of the using
block. DbContextTransaction.Dispose
方法将在using
块的末尾调用。 And it will automatically rollback the transaction if the transaction is not successfully committed (not called or encountered exceptions). 如果未成功提交事务(未调用或遇到异常),它将自动回滚事务。 Following is the source code of
SqlInternalTransaction.Dispose
method ( DbContextTransaction.Dispose
will finally delegate to it when using SqlServer provider): 以下是
SqlInternalTransaction.Dispose
方法的源代码(使用SqlServer提供程序时, DbContextTransaction.Dispose
将最终委托给它):
private void Dispose(bool disposing)
{
// ...
if (disposing && this._innerConnection != null)
{
this._disposing = true;
this.Rollback();
}
}
You see, it checks if _innerConnection
is not null, if not, rollback the transaction (if committed, _innerConnection
will be null). 您会看到,它检查
_innerConnection
是否不为null,否则检查回滚事务(如果已提交,则_innerConnection
为null)。 Let's see what Commit
does: 让我们看看
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);
}
}
As long as you will always be using SQL Server with EF, there is no need to explicitly use the catch to call the Rollback method. 只要您始终将SQL Server与EF一起使用,就无需显式使用catch来调用Rollback方法。 Allowing the using block to automatically rollback on any exceptions will always work.
允许using块自动回滚任何异常将始终有效。
However, when you think about it from the Entity Framework point of view, you can see why all examples use the explicit call to Rollback the transaction. 但是,从实体框架的角度考虑它时,您可以看到为什么所有示例都使用显式调用来回滚事务。 To the EF, the database provider is arbitrary and pluggable and the provider can be replaced with MySQL or any other database that has an EF provider implementation.
对于EF,数据库提供程序是任意的且可插入的,并且可以使用MySQL或具有EF提供程序实现的任何其他数据库替换该提供程序。 Therefore, from the EF point of view, there is no guarantee that the provider will automatically rollback the disposed transaction, because the EF does not know about the implementation of the database provider.
因此,从EF的角度来看,由于EF不知道数据库提供程序的实现,因此不能保证提供程序将自动回滚已处置的事务。
So, as a best practice, the EF documentation recommends that you explicitly Rollback -- just in case you someday change providers to an implementation that does not auto-rollback on dispose. 因此,作为最佳实践,EF文档建议您显式回滚-以防万一有一天您将提供程序更改为在处置时不会自动回滚的实现。
In my opinion, any good and well written provider will automatically rollback the transaction in the dispose, so the additional effort to wrap everything inside the using block with a try-catch-rollback is overkill. 在我看来,任何优秀且编写良好的提供程序都将自动在Dispose中回滚事务,因此用try-catch-rollback将所有内容包装在using块内的额外努力是过大的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.