MGD Software
Messages postés193Date d'inscriptionvendredi 1 septembre 2006StatutMembreDernière intervention23 avril 2022
-
4 mai 2018 à 14:54
MGD Software
Messages postés193Date d'inscriptionvendredi 1 septembre 2006StatutMembreDernière intervention23 avril 2022
-
4 mai 2018 à 19:00
Bonjour,
Je développe un programme de comptabilité en C#, utilisant une base de données Access.
La base a été créée avec Access 2010.
Elle comporte une table "Operations" ayant entre autres un champ "DateOps" de type Date/Heure et un champ "Montant" de type "Réel simple".
Lorsque j'exécute le code ci-dessous, j'ai une erreur "Type de données incompatible dans l'expression du critère." au niveau du ExecuteReader().
J'ai tenté de créer des objets OleDbParameter distincts puis de les ajouter à la commande avec Cmd.Parameters.Add, même résultat.
J'ai tenté aussi de remplacer AddWithValue(nom, valeur) par Add(new OleDbParameter(nom, valeur)), même résultat.
J'ai vérifié avec un point d'arrêt que Cmd.Parameters[0].Value.GetType().Name donnait bien "DateTime". Idem pour le second.
Pourquoi un paramètre DateTime en C# est incompatible avec un champ Date/Heure Access ???
Et je ne veux pas me passer des paramètres pour éviter une injection SQL avec le contenu des champs de date (encore qu'ils sont filtrés à la validation).
Le problème ne vient probablement pas du Sum(Montant) puisque si j'enlève la clause WHERE cela fonctionne.
Et d'autre part, dans une autre requête SELECT où je n'utilise pas de paramètre de date mais qu'un des champs est une date, la fonction GetDateTime() de l'OleDbDataReader ne provoque pas d'erreur.
[...]
OleDbCommand Cmd;
OleDbDataReader Rs;
DateTime dtDateDu = new DateTime(0);
DateTime dtDateAu = DateTime.Now;
DateTime dtDummy = new DateTime();
if (txtDateDu.Text != "" && DateTime.TryParse(txtDateDu.Text, out dtDummy)) dtDateDu = dtDummy;
if (txtDateAu.Text != "" && DateTime.TryParse(txtDateAu.Text, out dtDummy)) dtDateAu = dtDummy;
ReopenBase();
// Calcul du total utilisable (ne tient pas compte des dates de valeur)
// Si date de début vide (depuis début), le montant initial est pris en compte
Cmd = new OleDbCommand("SELECT Sum(Montant) AS Total FROM Operations WHERE DateOps BETWEEN @DateDu AND @DateAu", mCnx);
Cmd.Parameters.AddWithValue("@DateDu", dtDateDu);
Cmd.Parameters.AddWithValue("@DateAu", dtDateAu);
try
{
Rs = Cmd.ExecuteReader();
if (Rs.HasRows)
{
Rs.Read();
if (Rs.GetValue(0).GetType() == typeof(DBNull))
txtTotalUtil.Text = ((int)0).ToString("0.00");
else
txtTotalUtil.Text = (Rs.GetDouble(0) + (txtDateDu.Text != "" ? InitVal : 0)).ToString("#,##0.00");
}
Rs.Close();
}
catch (Exception ex) { Console.WriteLine(Cmd.CommandText + " => " + ex.Message); txtTotalUtil.Text = "Erreur"; }
[...]
MGD Software
Messages postés193Date d'inscriptionvendredi 1 septembre 2006StatutMembreDernière intervention23 avril 20222 4 mai 2018 à 19:00
Merci pour la réponse, mais elle est hors sujet.
J'ai précisé que je ne voulais pas placer les dates dans le texte de la requête, mais utiliser des paramètres.
L'article cité n'utilise pas de paramètres (dont les nom commencent obligatoirement par un "@" en C#)
Il suffit d'entrer des guillemets dans le texte de la date pour effectuer une injection SQL qui peut être très dangereuse pour la base de données. L'utilisation des valeurs dans le texte de la requête est une pratique dangereuse qu'il ne faut utiliser que quand on ne peut pas faire autrement (ou que les valeurs sont internes au programme et ne proviennent pas d'une saisie utilisateur).
Merci quand même pour t'être penché sur la question.