いくつかの単純化が可能です。まず、すべてのコマンドをトランザクション内に含める必要があります。これは、挿入されたレコードが厳密な関係にあり、部分的に完了したレコードのセットを持つことは意味がないという古典的なケースだからです。
using(MySqlConnection conn = new MySqlConnection(connStr))
{
conn.Open();
using(MySqlTransaction tr = conn.BeginTransaction())
{
...
// MySqlCommand code goes here
...
tr.Commit();
}
}
これで、挿入質問SQLを変更して、最後に挿入されたIDを返す2番目のステートメントを追加できます
string queryUpdateQuestions = @"INSERT INTO questions (.....);
SELECT LAST_INSERT_ID()";
using(MySqlCommand cmdUpdateQuestions = new MySqlCommand(queryUpdateQuestions, conn, tr))
{
// build the parameters for the question record
......
// Instead of ExecuteNonQuery, run ExecuteScalar to get back the result of the last SELECT
int lastQuestionID = Convert.ToInt32(cmdUpdateQuestions.ExecuteScalar());
..
}
MySqlCommandコンストラクターで、現在のトランザクションへの参照がどのように渡されるかに注意してください。これは、トランザクションが開かれている接続を操作するために必要です。
第二部では、物事はもう少し複雑です。 2番目のSQLステートメントを追加する同じトリックを、回答を挿入するループにも適用できますが、最初の質問が正しい場合は、逆方向にループする必要があります
string queryUpdateAnswers = @"INSERT INTO answers (question_id, answer)
VALUES (@question_id, @answer);
SELECT LAST_INSERT_ID()";
using(MySqlCommand cmdUpdateAnswers = new MySqlCommand(queryUpdateAnswers, conn, tr))
{
// next move the loop inside the using and prepare the parameter before looping to
// to avoid unnecessary rebuild of the parameters and the command
cmdUpdateAnswers.Parameters.Add("@answer", MySqlDbType.VarChar);
cmdUpdateAnswers.Parameters.Add("@question_id", MySqlDbType.Int32);
int lastAnswerID = 0;
// Loop backward so the last answer inserted is the 'correct' one and we could get its ID
for (int b=a; b >= 1; b--)
{
cmdUpdateAnswers.Parameters["@answer"].Value = ((TextBox)this.FindControl("txtAnswer" + b)).Text;
cmdUpdateAnswers.Parameters["@question_id"].Value = lastQuestionID;
lastAnswerID = Convert.ToInt32(cmdUpdateAnswers.ExecuteScalar());
}
....
}
これで、lastAnswerIDで質問を更新する最後のコマンドを実行できます
(最後の注意点として、question_idフィールドとanswer_idフィールドはvarcharではなくnumeric型であると思います。これには、これらのフィールドのパラメーターがvarcharではなくInt32である必要があります)