我有一个问题,我希望在一个事务中对不同的表进行插入操作。因此,如果事务失败,表中的任何一个都不会被不一致的数据污染。
问题还有另一个限制因素。表-2与表-1的主键(auto_increment)具有外键关系。因此,当我在Table-1和Table-2中添加新条目时,我需要在新的Table-2条目中添加Table-1的新主键,这是同一事务的一部分。
我正在使用MYSQLDataAdaptor来填充SB。
问题陈述有点棘手,如果我们需要更多澄清,请告诉我。
提前致谢!!
答案 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;
}