【问题标题】:Insert into 3 tables based on the sequence number from 1st insert in C#根据 C# 中第一次插入的序列号插入 3 个表
【发布时间】:2011-06-30 11:29:37
【问题描述】:

我在 Oracle 数据库中有 3 个表。在我的 asp.net C# 页面中,我将记录插入到所有三个表中,如下所示:

INSERT INTO contactMaster
   (contactID, FName, MName, LName) 
VALUES
   (contactID.NextVal, 'John', 'G', 'Garnet')

INSERT INTO contactPhone
  (contactPhoneID, contactID, contactType, phonenum)     
VALUES
  (contactPhoneID.NextVal, 1, 2, 1234567890)

INSERT INTO contactAddress
  (contactAddressID, contactID, addressType, PHN, Street, City)
VALUES
  (contactAddressID.NextVal, 1, 1, 287, 'Blooper St', 'New Yor')

我的问题是,我如何确保在 C# 中执行上述所有操作或不执行任何操作。

如果第 2 次或第 3 次插入失败,则一切都会失败。

【问题讨论】:

  • 与您的问题无关,但您应该在 SQL 查询中使用Bind variables/parameters...

标签: c# asp.net sql oracle


【解决方案1】:

使用 SQL 事务确保原子性:

public void RunOracleTransaction(string connectionString) {
  using (OracleConnection connection = new OracleConnection(connectionString))
  {
    connection.Open();

    OracleCommand command = connection.CreateCommand();
    OracleTransaction transaction;

    // Start a local transaction
    transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted);
    // Assign transaction object for a pending local transaction
    command.Transaction = transaction;

    try
    {
        command.CommandText = 
            "INSERT INTO contactMaster
               (contactID, FName, MName, LName) 
             VALUES
               (contactID.NextVal, 'John', 'G', 'Garnet')";
        command.ExecuteNonQuery();

        command.CommandText = 
            "INSERT INTO contactPhone
               (contactPhoneID, contactID, contactType, phonenum)     
             VALUES
               (contactPhoneID.NextVal, 1, 2, 1234567890)";
        command.ExecuteNonQuery();

        command.CommandText = 
            "INSERT INTO contactAddress
               (contactAddressID, contactID, addressType, PHN, Street, City)
             VALUES
               (contactAddressID.NextVal, 1, 1, 287, 'Blooper St', 'New Yor')";
        command.ExecuteNonQuery();

        transaction.Commit();
        Console.WriteLine("Both records are written to database.");
    }
    catch (Exception e)
    {
        transaction.Rollback();
        Console.WriteLine(e.ToString());
        Console.WriteLine("Neither record was written to database.");
    }
  }
}

C#:OracleTransaction

另类

插入语句可以移动到存储过程(最好在包中),因此只需要从 C# 中进行一次查询。

【讨论】:

    【解决方案2】:

    只是另一个想法 - 您可以使用一个 INSERT 语句进行插入,例如:

    INSERT ALL
    INTO contactMaster
       (contactID, FName, MName, LName) 
    VALUES
       (contactID, FName, MName, LName)
    INTO contactPhone
      (contactPhoneID, contactID, contactType, phonenum)     
    VALUES
      (contactPhoneID.NextVal, contactID, contactType, phonenum)
    INTO contactAddress
      (contactAddressID, contactID, addressType, PHN, Street, City)
    VALUES
      (contactAddressID.NextVal, contactID, addressType, PHN, Street, City)
    (SELECT contactID.NextVal AS contactID,
            'John' AS FName,
            'G' AS MName,
            'Garnet' AS LName,
            2 AS contactType,
            1234567890 AS phonenum,
            1 AS addressType,
            287 AS PHN,
            'Blooper St' AS Street,
            'New Yor' AS City
     FROM   dual)
    

    顺便说一句,您的原始插入似乎遇到了contactID 始终为1 的问题,而不管为contactMaster.contactID 生成的序列是什么。如果您想为每个表保留单独的 INSERT,您可以通过引用 contactID.CurrVal 获取最近生成的值。

    【讨论】:

      【解决方案3】:

      在第一个命令之前,开始一个transaction:

      start transaction
      

      在最后一条命令之后,提交事务:

      commit transaction
      

      您可以一次性将这些发送到数据库,也可以使用单独的命令。无论哪种方式,都将保留所有插入或不保留任何插入。

      【讨论】:

        猜你喜欢
        • 2022-01-23
        • 2019-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-03
        • 1970-01-01
        • 2019-04-19
        • 2014-11-12
        相关资源
        最近更新 更多