我尝试了解EF如何通过代码中的对象操作创建数据库请求。我的测试场景很简单:
using(var context = new Context())
{
var entity = context.Entities.First();
entity.A = "TST";
entity.B = "WrongValue";
context.SaveChanges();
}
我的想法是测试,EF如何处理交易。 使用正确的值更改A并使用错误的值更改B(不存在的FK) 我跟踪SQL Server DB中发生的事情。 我执行代码并没有任何更改DB,这是预期的。 奇怪的是,有两个独立的SQL请求,我不明白EF如何还原第一个。
答案 0 :(得分:4)
Entity Framework
和EntityFramework core
代码都是开源代码。您可以在
如果您看到Save method的内部代码(粘贴下面的代码快照),那么您可以在内部验证它是否在未提供外部事务时创建事务。
internal int SaveChangesInternal(SaveOptions options, bool executeInExistingTransaction)
{
AsyncMonitor.EnsureNotEntered();
PrepareToSaveChanges(options);
var entriesAffected = 0;
// if there are no changes to save, perform fast exit to avoid interacting with or starting of new transactions
if (ObjectStateManager.HasChanges())
{
if (executeInExistingTransaction)
{
entriesAffected = SaveChangesToStore(options, null, startLocalTransaction: false);
}
else
{
var executionStrategy = DbProviderServices.GetExecutionStrategy(Connection, MetadataWorkspace);
entriesAffected = executionStrategy.Execute(
() => SaveChangesToStore(options, executionStrategy, startLocalTransaction: true));
}
}
ObjectStateManager.AssertAllForeignKeyIndexEntriesAreValid();
return entriesAffected;
}
因此,您的下面的代码将在内部包装在您可以在SQL事件探查器中验证的事务中。
using(var context = new Context())
{
var entity = context.Entities.First();
entity.A = "TST";
entity.B = "WrongValue";
context.SaveChanges();
}
但是,SQL事件探查器不会开始记录事务,因此您需要在跟踪设置中配置它。请参阅下面的SQL profiler新Trace设置的屏幕截图,在这里,我检查了Show All events
。之后显示Transaction
类别。您可以订阅Begin Tran
,Commit Tran
和Rollback Tran
事件来验证事务语句。当您运行场景时,您可以看到应记录Begin和Rollback。