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

时间:2015-01-20 11:04:02

标签: c# mysql database

我有一个问题,我希望在一个事务中对不同的表进行插入操作。因此,如果事务失败,表中的任何一个都不会被不一致的数据污染。

问题还有另一个限制因素。表-2与表-1的主键(auto_increment)具有外键关系。因此,当我在Table-1和Table-2中添加新条目时,我需要在新的Table-2条目中添加Table-1的新主键,这是同一事务的一部分。

我正在使用MYSQLDataAdaptor来填充SB。

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

提前致谢!!

3 个答案:

答案 0 :(得分:1)

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

 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();
}

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

{
    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;
}