Mysql
 sql >> Base de données >  >> RDS >> Mysql

Deux requêtes d'insertion avec des champs liés

Certaines simplifications sont possibles. Tout d'abord, vous devez inclure toutes vos commandes dans une transaction car c'est le cas classique où les enregistrements insérés sont strictement liés et cela n'a pas de sens d'avoir un ensemble d'enregistrements partiellement complétés.

using(MySqlConnection conn = new MySqlConnection(connStr))
{
    conn.Open();
    using(MySqlTransaction tr = conn.BeginTransaction())
    {
        ...
        // MySqlCommand code  goes here
        ...
        tr.Commit();
   }
}

Maintenant, vous pouvez modifier votre question d'insertion sql pour ajouter une deuxième instruction qui renvoie le dernier identifiant inséré

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

    ..

 }

Remarquez comment, au niveau du constructeur MySqlCommand, est transmise la référence à la transaction en cours. Ceci est nécessaire pour travailler avec une connexion qui a une transaction ouverte.

Les choses sont un peu plus complexes pour la deuxième partie. La même astuce pour ajouter une deuxième instruction sql pourrait également être appliquée à la boucle qui insère les réponses, mais vous devez revenir en arrière si la première question est la bonne

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

Vous pouvez maintenant exécuter la dernière commande qui met à jour la question avec le lastAnswerID

(Une dernière note, je suppose que les champs question_id et answer_id sont de type numeric, pas varchar, cela nécessite que les paramètres de ces champs soient un Int32 et non un varchar)