纯 EF 操作 + 原生 SQL 混用,使用事务

using (var scope = new TransactionScope()) // 开启“超级保护罩”
using (var dc = new VincentDataClassesDataContext(comClass.Vincent_Class.connString))
{
    // ---- 第1部分:纯 EF 操作(实体方式) ----
    // 比如:新增一条操作日志
    var log = new SystemLog 
    { 
        Action = "开始导入订单", 
        CreateTime = DateTime.Now 
    };
    dc.SystemLogs.InsertOnSubmit(log); // EF 的添加操作

    // ---- 第2部分:您之前的原生 SQL 操作 ----
    dc.ExecuteCommand("UPDATE TempOrders SET ErrorMessage = '物料不存在' WHERE ...");
    dc.ExecuteCommand("UPDATE TempOrders SET ErrorMessage = '订单号重复' WHERE ...");
    dc.ExecuteCommand("INSERT INTO Orders SELECT ... FROM TempOrders WHERE ...");
    dc.ExecuteCommand("DELETE FROM TempOrders WHERE ErrorMessage IS NULL");

    // ---- 第3部分:又回来用 EF 操作 ----
    // 比如:修改订单表里某条记录的状态(纯实体操作)
    var firstOrder = dc.Orders.FirstOrDefault(o => o.OrderNo == "PO-001");
    if (firstOrder != null)
    {
        firstOrder.Status = "已导入完成";
    }

    // ---- 提交所有 EF 的修改(InsertOnSubmit / 修改实体) ----
    // 注意:这一句非常智能!它会自动把上面的 InsertOnSubmit 和实体修改,
    // 连同 ExecuteCommand 执行的 SQL,全部打包进同一个事务里!
    dc.SubmitChanges();

    // ---- 盖章生效 ----
    scope.Complete(); 
}
// 如果中间任何代码(包括 SubmitChanges 内部)报错,事务自动回滚,数据库纹丝不动。

引用(很重要!)

使用 TransactionScope 需要添加对 System.Transactions.dll 的引用。

  • 在您的项目引用(Reference)里,勾选 System.Transactions
  • 在代码头部加上:using System.Transactions;

特别说明:在 C# 中,using 语句后面如果紧跟另一个 using 语句,可以省略外层的大括号。编译器会自动将内层 using 的大括号作为外层 using 的作用域