c# - 实体框架 SaveChanges 是如何工作的?
问题描述
我试图了解 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 中发生的事情。我执行代码并且数据库中没有任何变化,这是预期的。奇怪的是有两个独立的 SQL 请求,我不明白 EF 如何恢复第一个。
解决方案
Entity Framework
和代码都是EntityFramework core
开源的。您可以在以下位置查看代码
如果您看到Save 方法的内部代码(粘贴下面的代码快照),那么您可以验证它是否在内部创建了一个事务,如果没有提供外部事务。
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 Profiler 中验证的事务中。
using(var context = new Context())
{
var entity = context.Entities.First();
entity.A = "TST";
entity.B = "WrongValue";
context.SaveChanges();
}
但是,SQL 探查器不会开始记录事务,因此您需要在跟踪设置中进行配置。请参阅下面的 SQL 探查器新跟踪设置的屏幕截图,在这里,我检查了Show All events
. 在Transaction
显示该类别之后。您可以订阅Begin Tran
,Commit Tran
和Rollback Tran
事件来验证交易语句。当您将运行您的方案时,您可以看到应该记录 Begin 和 Rollback。
推荐阅读
- swift - AnyView 阻止查看更新
- javascript - 如何将for循环中的元素传递给父组件?
- python-3.x - Python 多重继承 - 值不可访问
- javascript - MiniCssExtractPlugin 中的字体路径错误
- android - 如何使用标准类将自定义对象添加到 Firestore?
- linux - 如何在 mininet Python 脚本中运行 ARP?
- python - Python Bokeh Serve - DEBUG:bokeh.server.contexts:Scheduling 1 session to discard
- html - 在 HTML 中引用本地文件图像文件
- swift - 按下触摸隐藏/显示 UIImage,并将数字从 10 倒数到 0
- python - 通过python打开特定大小的.exe文件