返回

C# 事务处理:向主从表插入数据最佳实践

windows

# ** C# 中使用 SqlTransaction 向主从表插入数据的最佳实践

## 问题陈述

在 C# 中使用事务(SqlTransaction)向主表(maestro)和从表(detalles)插入数据时,我们遇到了一个问题。虽然我们成功地插入了数据,但意识到我们的方法不佳,因为外键字段是从数据层传递到从表的,而它应该从表示层传递。这导致无法捕获主表中的自增值(MaestroId)并将其传递给从表。

## 解决方案

为了解决这个问题,我们提出了以下解决方案:

1. 数据层

我们修改了数据层代码以获取自增主键:

// 在 Maestro 表中插入主记录,获取自增主键作为输出参数
using (SqlCommand command = new SqlCommand("sp_InsertMaster", connection, transaction))
{
    command.CommandTimeout = 20;
    command.CommandType = CommandType.StoredProcedure;
    command.Parameters.AddWithValue("@Name", name);
    SqlParameter outputParameter = new SqlParameter("@MaestroId", SqlDbType.Int)
    {
        Direction = ParameterDirection.Output
    };
    command.Parameters.Add(outputParameter);
    command.ExecuteNonQuery();
    int maestroId = Convert.ToInt32(outputParameter.Value); // 获取自增主键

    // 在 Detalles 表中插入从记录,传递自增主键
    foreach (var detail in masterDetails)
    {
        using (SqlCommand command = new SqlCommand("sp_InsertDetail", connection, transaction))
        {
            command.CommandTimeout = 20;
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.AddWithValue("@MaestroId", maestroId);
            command.Parameters.AddWithValue("@LastName", detail.LastNames);
            command.ExecuteNonQuery();
        }
    }
}

2. 逻辑层

我们移除了从数据层传递外键字段的代码,将其委托给表示层:

public void RegisterMasterAndDetail(string name, List<EN_MasterDetail> masterDetails)
{
    using (BD_MasterDetail bdMasterDetail = new BD_MasterDetail())
    {
        bdMasterDetail.RegisterMasterAndDetail(name, masterDetails);
    }
}

3. 表示层

我们负责向数据层传递正确的自增主键:

public void RegisterMasterAndDetail(string name, List<EN_MasterDetail> masterDetails)
{
    using (RN_MasterDetail rnMasterDetail = new RN_MasterDetail())
    {
        EN_MasterDetail masterDetail = new EN_MasterDetail()
        {
            LastNames = "Melgar",
            Age = 30,
            Height = 1.75
        };

        rnMasterDetail.RegisterMasterAndDetail("Master 1", new List<EN_MasterDetail> { masterDetail });
    }
}

关键要点

  • 使用 SqlTransaction 来确保原子性。
  • 通过输出参数捕获主表的自增主键。
  • 委托表示层传递外键字段。
  • 将事务处理委托给数据层,逻辑层和表示层只负责业务逻辑和交互。

## 结论

通过实施这些改进,我们建立了一个健壮且可维护的事务处理机制来向主从表插入数据。这种方法消除了以前存在的限制,并确保了数据的完整性。

## 常见问题解答

  1. 为什么事务处理如此重要?
    事务处理确保数据的原子性、一致性、隔离性和持久性(ACID)。它可以防止由于系统故障或并发访问导致数据不一致。

  2. 输出参数的优点是什么?
    输出参数允许我们在插入或更新操作后检索自增值和其他生成的值。

  3. 何时使用存储过程?
    存储过程用于封装常见的数据库操作,从而提高性能、安全性并减少代码重复。

  4. 表示层在事务处理中的作用是什么?
    表示层负责收集和验证用户输入,并将其传递给逻辑层和数据层。

  5. 如何调试事务处理问题?
    使用调试器、日志记录和分析工具来识别和解决事务处理中的异常和错误。