一次在多个表中添加数据,它们之间有外键约束

Adding data in multiple tables in one shot with a foreign key constraints between them

我有一个问题,我想在一个事务中对不同的 table 执行插入操作。因此,如果事务失败,table 中的 none 会被不一致的数据污染。

这个问题还有一个限制条件。 Table-2与Table-1的主键(auto_increment)有外键关系。因此,当我在 Table-1 和 Table-2 中添加新条目时,我需要在新的 Table-2 条目中添加 Table-1 的新主键,即同一笔交易的一部分。

我正在使用 MYSQLDataAdaptor 来填充 SB。

问题陈述有点棘手,如果我们需要更多说明,请告诉我。

提前致谢!!

我认为只有跟踪 Table-1 主键并使用预先计算的主键生成插入内容才有可能。所以你必须确定,没有人不能同时将任何数据插入同一个 table.

我已经使用事务概念解决了这个问题。

 MySqlDataAdapter [] all_adapters = new MySqlDataAdapter[2];
 DataTable [] data_tables = new DataTable[2];

for (int i = 0; i < 2; i++ )
{
    all_adapters[i] = new MySqlDataAdapter(query[i], connection);
    MySqlCommandBuilder cb = new MySqlCommandBuilder(all_adapters[i]);
    all_adapters[i].InsertCommand = cb.GetInsertCommand();

    data_tables[i] = new DataTable();
    all_adapters[i].Fill(data_tables[i]);
}

MySqlTransaction transaction = connection.BeginTransaction();

try
{
    for (int i = 0; i < 2; i++ )
    {
         all_adapters[i].InsertCommand.Transaction = transaction;

         if (i == 0)
         {
              ... Add entry in table-1

              // Fetch new auto_increment primary key of table-1
              string new_query = "SELECT LAST_INSERT_ID();";
              MySqlCommand cmd = new MySqlCommand(new_query, connection);
              int primary_id_table1 = Convert.ToInt32(cmd.ExecuteScalar());
         }
        else 
        {
             ... Add entry in table-2.
             Use primary_id_table1 to populate the foreign key in table-2
        }
    }

    transaction.Commit();
}
catch (Exception e)
{
     transaction.Rollback();
}

这将确保 table 在数据库中同时更新,或者 table 中的 none 得到更新,因为交易效果被回滚。这将有助于维护数据库的一致性。因此,在给定事务中维护 ACID 属性。

我在这个问题上挠了挠头,直到我终于意识到这个问题。我试图用自动递增的 ID 字段更新两个主要的 table,然后用前两个 table 的记录中的 ID 值更新第三个 table,所有这些都在一个交易。我发现数据集中的 AutoIncrement Primary Key 字段不会是更新后写入的记录的实际值(它们的字段将有值,但不一定是正确的)。当读取 table 模式时,它将只是种子值序列中的下一个。因此,要处理此问题,请将 RowUpdated 处理程序添加到您的 DataAdapter 并读取 command.LastInsertedId 属性。这样,AutoIncrement 值就是 table 中写入的实际值。然后将新记录添加到第三个 table 有效。

{
    MySqlDataAdapter daAll = new MySqlDataAdapter("Select * from courses;Select * from productsku;Select * from productcourseassociation;", sqlConn);
    MySqlDataAdapter daCourses = new MySqlDataAdapter("Select * from courses;", sqlConn);
    MySqlDataAdapter daSku = new MySqlDataAdapter("Select * from productsku;", sqlConn);
    MySqlDataAdapter daAssoc = new MySqlDataAdapter("Select * from productcourseassociation;", sqlConn);
    daCourses.RowUpdated += DaCourses_RowUpdated;
    daSku.RowUpdated += DaSku_RowUpdated;
    DataSet ds = new DataSet();
    daAll.FillSchema(ds, SchemaType.Source);

    daCourses.TableMappings.Add("courses", "Table");
    daSku.TableMappings.Add("productsku", "Table1");
    daAssoc.TableMappings.Add("productcourseassociation", "Table2");
    ForeignKeyConstraint fkConstraint1 = new ForeignKeyConstraint("fk1", ds.Tables[0].Columns["courseid"], ds.Tables[2].Columns["courseid"]);
    ForeignKeyConstraint fkConstraint2 = new ForeignKeyConstraint("fk2", ds.Tables[1].Columns["skuid"], ds.Tables[2].Columns["skuid"]);
    ds.Tables[2].Constraints.Add(fkConstraint1);
    ds.Tables[2].Constraints.Add(fkConstraint2);

    MySqlCommandBuilder cbCourses = new MySqlCommandBuilder(daCourses);
    MySqlCommandBuilder cbSku = new MySqlCommandBuilder(daSku);
    MySqlCommandBuilder cbAssoc = new MySqlCommandBuilder(daAssoc);

    DataRow courseRow = ds.Tables[0].NewRow();
    courseRow["coursename"] = courseName;
    ds.Tables[0].Rows.Add(courseRow);

    r = ds.Tables[1].NewRow();
    r["skudesc"] = courseName;
    r["duration"] = 1;
    ds.Tables[1].Rows.Add(r);

    r = ds.Tables[1].NewRow();
    r["skudesc"] = courseName;
    r["duration"] = 3;
    ds.Tables[1].Rows.Add(r);

    r = ds.Tables[1].NewRow();
    r["skudesc"] = courseName;
    r["duration"] = 12;
    ds.Tables[1].Rows.Add(r);        

    daCourses.Update(ds, "Table");
    daSku.Update(ds, "Table1");     
    daAssoc.Fill(ds, "Table2");

    int courseId = Convert.ToInt32(courseRow["courseid"]);
    DataRow[] skurows = ds.Tables[1].Select(String.Format("skudesc='{0}'", courseName));
    foreach (DataRow dr in skurows)
    {
        r = ds.Tables[2].NewRow();
        r["skuid"] = dr["skuid"];
        r["courseid"] = courseId;
        ds.Tables[2].Rows.Add(r);
    }
    daAssoc.Update(ds, "Table2");
}   

private void DaSku_RowUpdated(object sender, MySqlRowUpdatedEventArgs e)
{
    System.Diagnostics.Debug.WriteLine("Row updated");
    e.Row["skuid"] = e.Command.LastInsertedId;
}

private void DaCourses_RowUpdated(object sender, MySqlRowUpdatedEventArgs e)
{
    System.Diagnostics.Debug.WriteLine("Row updated");
    e.Row["courseid"] = e.Command.LastInsertedId;
}