Bonjour à tous,

Je travaille sur un projet c# / SqlServer. J'ai crée des classes pour formaliser l'accès aux serveurs, la création de requêtes paramétrées, la gestion des exceptions pendant l'exécution des requêtes, etc...

le schéma est toujours le même : j'appelle une méthode avec en paramètres le nom du serveur, de la base, la requête en chaîne de caractères, et une liste de paramètres, celle ci effectue la requête et se charge de traitements spéciaux en cas d'exceptions.

Un exemple:
Code : 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
/// <summary>
        /// Exécute une requête d'écriture sur le serveur par défaut
        /// </summary>
        /// <param name="query">requête</param>
        /// <param name="prms">liste des paramètres</param>
        /// <exception cref="SqlException">exception levé en cas d'erreur SQL</exception>
        /// <exception cref="Exception">exception levé en cas d'erreur de connection (5 tentatives)</exception>
        /// <exception cref="Exception">exception levé, erreur inconnue</exception>
        public static void ExecQuery(string query, List<DbParam> prms)
        {
            int attemps = 0;
 
            while (attemps < 5)
            {
                using (IDbConnection c = DataProviderFactory.GetInstance().GetSqlConnection())
                {
                    try
                    {
                        c.Open();
                        IDbCommand cmd = c.CreateCommand();
                        cmd.CommandTimeout = 180;
                        cmd.CommandText = query;
 
                        AddParamsAndValues(cmd, prms);
 
                        cmd.ExecuteNonQuery();
                        attemps = 5;
                    }
                    catch (SqlException e)
                    {
                        if (e.Number == 1 || e.Number == 17142)
                        {
                            if (attemps < 4)
                            {
                                attemps++;
                                System.Threading.Thread.Sleep(10000);
                            }
                            else
                                throw new ServerException("La connexion au serveur a échoué malgré 5 tentatives.");
                        }
                        else
                            throw e;
                    }
                    catch
                    {
                        throw new Exception("Une erreur de type inconnue est survenue.");
                    }
                }
            }
        }
Cependant, mon programme utilise des requêtes préparées : je doit ouvrir une connexion, créer des paramètres, préparer la requête, et ensuite je rentre dans une boucle (pouvant contenant plusieurs dizaines d'itérations) et pour chaque itération j'exécute la requête après avoir renseigné la valeur des paramètres.

Concrètement, cela donne un truc de ce genre :
Code : 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
 
using (SqlConnection c = DataProviderFactory.GetInstance().GetConnection())
{
        try
        {
                c.Open();
                SqlCommand cmd = c.CreateCommand();
                SqlCommand.commantText = "insert into Serveur.dbo.Table (id, nom, prix_public) values (@id, @nom, @value)";
                // createParam est une méthode créant un paramètre pour l'objet Command
                CreateParam(cmd, "@id", DbType.Int32, 4);
                CreateParam(cmd, "@nom", DbType.String, 20);
                CreateParam(cmd, "@value", DbType.Decimal, 24, 6);
                cmd.Prepare();
                // beaucoup de code sans rapport ici
 
                for(int i = 0; i < unTableauQuelconque.Count; i++)
                {
                        // AddValue renseigne la valeur pour des paramètres déjà existants
                        AddValue(cmd, "@id", unTableauQuelconque[i].["id"]);
                        AddValue(cmd, "@nom", unTableauQuelconque[i].["nom"]);
                        AddValue(cmd, "@value", unTableauQuelconque[i].["prix"]);
 
                        cmd.ExecuteNonQuery();
                }
        }
        catch (Exception e)
        {
                // gestion des exceptions
        }
}
J'aimerais remplacer ce code par celui ci ( que je trouve beaucoup plus beau ):

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
 
for(int i = 0; i < unTableauQuelconque.Count; i++)
{
        List<DbParam> prms = new List<DbParam>();
        prms.Add(new DbParam("@nom", DbType.String, 20, unTableauQuelconque[i].["nom"]));
        prms.Add(new DbParam("@id", DbType.Int32, 4, unTableauQuelconque[i].["id"]));
        prms.Add(new DbParam("@value", DbType.Decimal, 24, 6, unTableauQuelconque[i].["prix"]));
        ExecQuery("insert into Serveur.dbo.Table (id, nom, prix_public) values (@id, @nom, @value)", prms)
}
Tout ça pour en venir à ma question : quel est le meilleur code ? Je n'arrive pas à le déterminer : je n'aime pas les requêtes préparés car ça m'oblige à utiliser une connexion persistante avec le serveur et que c'est plus contraignant à coder (réécriture de l'accès à la base, réécriture du traitement des exceptions, etc...) mais en contrepartie c'est A PRIORI plus rapide, mais la encore je ne connais pas la différence de perfs entre requêtes préparés et non préparés.

Merci pour vos conseils.