Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Duas consultas de inserção com campos vinculados


Alguma simplificação é possível. Antes de tudo, você precisa incluir todos os seus comandos dentro de uma transação, porque este é o caso clássico em que os registros inseridos estão estritamente em relacionamentos e não faz sentido ter algum conjunto de registros parcialmente concluído.
using(MySqlConnection conn = new MySqlConnection(connStr))
{
    conn.Open();
    using(MySqlTransaction tr = conn.BeginTransaction())
    {
        ...
        // MySqlCommand code  goes here
        ...
        tr.Commit();
   }
}

Agora, você pode alterar sua pergunta de inserção sql para adicionar uma segunda instrução que retorna o último id inserido
 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());

    ..

 }

Observe como, no construtor MySqlCommand, é passada a referência para a transação atual. Isso é necessário para trabalhar com uma conexão que tenha uma transação aberta.

As coisas são um pouco mais complexas para a segunda parte. O mesmo truque para adicionar uma segunda instrução sql pode ser aplicado também ao loop que insere as respostas, mas você precisa fazer um loop para trás se a primeira pergunta for a correta
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());
    }
    ....
}

Agora você pode executar o último comando que atualiza a pergunta com o lastAnswerID

(Uma última nota, suponho que os campos question_id e answer_id sejam do tipo numérico, não varchar, isso requer que os parâmetros para esses campos sejam um Int32 e não um varchar)