Bonjour,

J'ai un problème que je ne m'explique pas...

Voici une méthode que j'ai écris qui permet de supprimer une ligne dans une table de type "clé/valeur", en vérifiant que la ligne n'est pas référencée dans une autre table par une clé étrangère.

Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
        public bool DeleteSimpleValue(string table, int id)
        {
            using (SqlCommand cmd1 = Cnx.CreateCommand(), cmd2 = Cnx.CreateCommand())
            {
                SqlParameter pId = cmd2.Parameters.Add("id", SqlDbType.Int);
                pId.Value = id;
                cmd1.CommandText = "SELECT FK.TABLE_NAME  [table], concat('select count(*) from [', FK.TABLE_NAME, '] fk where fk.[', CU.COLUMN_NAME, '] in (select p.[', PT.COLUMN_NAME, '] from [', PK.TABLE_NAME, '] p where p.id = @id)') query FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME INNER JOIN (SELECT i1.TABLE_NAME, i2.COLUMN_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1 INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY') PT ON PT.TABLE_NAME = PK.TABLE_NAME where PK.TABLE_NAME = @name";
                SqlParameter pName = cmd1.Parameters.Add("name", SqlDbType.VarChar, 50);
                pName.Value = table;
                cmd1.Prepare();
                SqlDataReader dr = cmd1.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult);
                while (dr.Read())
                {
                    cmd2.CommandText = dr.GetString(1);
                    cmd2.Prepare();
                    int nb = (int)cmd2.ExecuteScalar();
                    if (nb > 0)
                    {
                        MessageBox.Show(string.Format("This {0} is referenced in another table : {1}", table, dr.GetString(0)));
                        dr.Close();
                        return false;
                    }
                }
                dr.Close();
 
                cmd2.CommandText = string.Format("delete {0} where id = @id", table);
                cmd2.Prepare();
                cmd2.ExecuteNonQuery();
                return true;
            }
        }

Le programme plante au premier appel de la ligne "int nb = (int)cmd2.ExecuteScalar();" avec une erreur comme quoi j'ai déjà un DataReader ouvert sur ma Command, et que je devrais le fermer avant d'en réouvrir un autre...

Sauf que... c'est le premier appel à cmd2 !
Oui, cmd1, qui est sur la même connexion, a bien un DataReader ouvert, mais ce n'est pas le même objet...

Que se passe-t-il ?