C# Entity Framework中实现事务回滚
在使用Entity Framework对关联的主从表进行数据添加时,若需保证多个表操作的原子性,可利用TransactionScope实现事务回滚。当部分操作失败时,数据库会自动撤销已提交的数据,确保数据一致性。
使用 TransactionScope 实现 EF 事务回滚
在C#的Entity Framework开发中,经常遇到需要在同一逻辑单元内对多个实体进行操作的情况。例如,同时插入“国家”和“州”两个表的数据。如果其中一个步骤失败(如代码抛出异常),我们希望之前成功写入的数据能够一并撤销,这就是事务回滚的核心作用。
以下展示了两张存在主外键关系的表结构示意图:
第一步:准备事务环境与上下文
目的:初始化用于管理分布式事务的范围和EF的数据库上下文。
- 入口:使用
using (TransactionScope ts = new TransactionScope())包裹核心业务代码。 - 动作:在事务范围内创建 EF 的 DbContext 实例(示例中为
CountryDetailsEntities)。 - 参数:
DbContext也推荐使用using语句管理,确保资源释放。
第二步:执行主表与从表的添加操作
目的:模拟正常的业务数据插入流程。
- 入口:构建实体对象并加入集合。
- 动作:
Country country = new Country();
country.CountryName = "USA";
db.Countries.Add(country);
调用db.SaveChanges()将主表数据暂存至本地缓存,此时尚未真正同步到物理数据库(具体行为受EF版本和配置影响,但在TransactionScope上下文中会跟随事务提交)。
第三步:设置异常触发点与验证逻辑
目的:模拟在插入从表时发生错误,以测试回滚机制。
- 输入参数:检查主表ID是否正确生成。
if (country.CountryID > 0)。 - 关键动作:执行可能导致异常的操作。示例中使用了
int total = 10 / a;(其中a=0)来强制抛出DivideByZeroException。 - 观察状态:正常情况下应继续添加 State 对象:
State state = new State();
state.CountryID = country.CountryID;
state.StateName = "NewYork";
db.States.Add(state);
第四步:确认事务并提交或回滚
目的:根据执行结果决定是否让变更持久化。
- 入口:
ts.Complete()放置在using块末尾。
如果代码顺利执行至此,事务被标记为已完成;若在中间任何地方发生未捕获异常,程序跳转到catch块。 - 完成判断:
- 正常情况:调用ts.Complete(),所有数据库操作被锁定并随事务一起提交。
- 异常情况:进入catch (Exception ex) { throw; }区域。由于TransactionScope未收到 Complete 信号且检测到异常,会自动取消当前事务,之前对数据库的所有修改将被回滚。
class Program
{
static void Main(string[] args)
{
try
{
using (TransactionScope ts = new TransactionScope())
{
using (CountryDetailsEntities db = new CountryDetailsEntities())
{
// 1. 添加主表数据
Country country = new Country();
country.CountryName = "USA";
db.Countries.Add(country);
db.SaveChanges();
if (country.CountryID > 0)
{
// 2. 模拟异常:除以零
int a = 0;
int total = 10 / a;
// 3. 理论上不会执行到这里
State state = new State();
state.CountryID = country.CountryID;
state.StateName = "NewYork";
db.States.Add(state);
db.SaveChanges();
}
}
// 4. 只有无异常才会提交事务
ts.Complete();
}
}
catch (Exception ex)
{
// 5. 异常发生后,事务自动回滚,数据库中无任何新增记录
throw;
}
}
}
总结
通过上述代码可以看出,TransactionScope 极大地简化了EF中的事务处理。无需手动编写复杂的SQL存储过程或显式开启/提交事务。一旦在执行链路上抛出异常,所有的 SaveChanges 都会失效。在实际生产环境中,建议将日志记录整合进 catch 块以便追踪问题根源。
以上就是关于 C# Entity Framework 中利用 TransactionScope 实现事务回滚的详细内容,更多关于数据库事务控制的相关资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













