Bonjour,
Je suis nouveau sur ce forum et j'ai l'occasion de travailler avec AutoCAD 2013 en tant que développeur C# (ce langage est, lui aussi, nouveau pour moi).
Après avoir suivi le super cours fait par Gile pour créer un modèle sur Visual Studio, je m'attaque maintenant à connecter une base de données Access à mon projet dans le but d'afficher une fenêtre dans AutoCAD avec les informations présentes dans ma base. C'est là que les choses se corsent...
J'ai tout d'abord essayé sans passer par autoCAD, et cela marche très bien: j'arrive à accéder aux infos de ma bdd.
Puis, je l'ai intégré à mon projet et au lancement de autoCAD, lorsque je clique sur le bouton "afficher le contenu de ma base", un message d'erreur apparaît.
J'ai tenté des points d'arrêts et quelques try catch pour en arriver à la conclusion que je n'arrive pas à ouvrir une connexion. Pourtant, dans projet=>Propriété=>paramètres, j'ai ajouté correctement ma base. Voici un petit bout de code:
<div class="code">
private OleDbConnection cn = new OleDbConnection(AcadCs2013.Properties.Settings.Default.maBase);
private OleDbCommand com;
private void button1_Click(object sender, EventArgs e)
{
try
{
cn.Open();
}
catch (Exception aze) {
MessageBox.Show("Erreur ici !");
}
com = new OleDbCommand("SELECT * FROM usager", cn);
OleDbDataReader dr;
dr = com.ExecuteReader();
dr.Read();
do
{
MessageBox.Show(dr["Nom"].ToString());
} while (dr.Read());
dr.Close();
cn.Close();
}
</div>
Lorsque je compile et que je clique sur le bouton, le message "Erreur ici !" apparait. Puis le message d'erreur AutoCAD que j'ai linké au dessus apparait.
J'attends votre avis, merci d'avance.
Maxime
PS:
Ma config:
- Visual Studio 2010
- AutoCAD 2013
- Access 2010
Balises :

Lien permanent Réponse de gile le 6 décembre 2012 à 15:44 Salut,
Tu ne semble pas très curieux.
As-tu déroulé "Détails" dans la boite de dialogue ? tu devrais y trouver des information sur ce qui a généré l'exception.
Dans le catch, tu peux aussi récupérer des informations intéressantes concernant l'exception:
catch (Exception exn) { MessageBox.Show("Erreur: {0}\nCode: {1}\nTrace: {2}", exn.Message, exn.ErrorCode, exn.Stacktrace);
Dans tous les cas, le try ne concerne que l'ouverture de la connexion à la base de donnée et si une exception est lancée à cet endroit, ce qui semble se passer, le programme continue ensuite en essayant de lire (ExecuteReader) dans une base de données dont la connexion n'est pas ouverte, ce qui ne manque pas de provoquer une nouvelle exception : celle qui affiche la boite de dialogue dans AutoCAD.
Les exceptions générées par DbConnection.Open() sont de deux types :
- InvalidOperationException si la connexion est déjà ouverte à partir de ce programme.
- DbException dans les autres cas (voir alors les propriétés Message et ErrorCode de l'exception).
As tu essayé avec la chaîne de connexion "en dur" :
private OleDbConnection cn = new OleDbConnection
cn.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=<ici le chemin complet du fichier .accdb>"
Si, comme tu le dis, tu débutes en .NET, accéder aux bases de données n'est certainement pas l'exercice le plus facile pour commencer...
Lien permanent Réponse de Maxence DELANNOY le 6 décembre 2012 à 18:52 Tout à fait d'accord avec Gilles. Tu dois inclure tout ton code dans le try-catch, car si l'ouverture de la connexion échoue, le reste du code va échouer également.
Ensuite, il faut éviter le catch (Exception ... car là tu attrapes toutes les exceptions. Il faut essayer d'"attraper" toutes les exceptions spécifiques et fournir une réponse adaptée pour chacune d'entre elles. Par exemple si tu as une exception InvalidOperationException, tu peux afficher le message explicite "La connexion à la base de données est déjà ouverte." Si c'est une OleDbException, tu peux afficher plus de détails :
string errorMessages = "";
for (int i = 0; i < e.Errors.Count; i++)
{
errorMessages += "Index #" + i + "\n" +
"Message: " + e.Errors[i].Message + "\n" +
"NativeError: " + e.Errors[i].NativeError + "\n" +
"Source: " + e.Errors[i].Source + "\n" +
"SQLState: " + e.Errors[i].SQLState + "\n";
}
Et je placerait les Close dans un bloc finally et le OleDbDataReader dans un bloc using

Lien permanent Réponse de Serge Camiré le 7 décembre 2012 à 4:02 Salut Maxime,
Je ne reprendrai pas ce qui a déjà été dit. J'indiquerai que plus les détails du problème sont exposés, plus les chances de cerner le problème et trouver une solution augmentent.
Pour moi, il y a déjà quelques irritants comme instancier et initialiser la nouvelle connexion à partir d'une variable globale. Elle devrait être à l'intérieur du Try. Peut-être que le problème s'y est déjà manifesté.
C'est une question de choix mais au lieu d'utiliser des Settings, j'y serais allé avec une simple variable pour commencer afin de ne pas mettre trop de nouveautés d'un coup. Plus tard, particulièrement avec avec les chaines de connexion, on pourra utiliser le app.config (où le app prend le nom de ton application). Ça permet ultérieurement de modifier les variable (i.e. ici le provider) sans rouvrir et recompiler le code (voir comment créer le app.config à http://www.siteduzero.com/tutoriel-3-593514-creer-le-fichier-de-con...).
Pour ce qui est des chaines de connexion, tu peux toujours vérifier auprès du site http://www.connectionstrings.com/ pour voir si la tienne est compatible.
Autre conseil: ta routine d'erreur devrait prévoir une action pour fermer la connexion en cas de problème.
Pour terminer, Visual Studio fournit plein d'Assistant pour créer des sources de données et des Dataset afin de remplir des DataGridView. Une fois qu'on a vérifier l'état de la connexion (toujours via l'assistant) on peut continuer à coder, tester et même modifier le chemin de la base de données lors de l'exécution.
Lien permanent Réponse de Maxime D le 7 décembre 2012 à 10:10 Salut,
Merci pour vos réponses rapides et détaillées.
Ce que je ne comprends pas c'est que lorsque j'ai essayé de me connecter à ma BDD et d'afficher des données en passant par un windows form, ça à marché (j'ai suivi un tutoriel). Par contre en passant par AutoCAD ça plante. Gile, j'ai essayé avec une connexion "en dur" et ça ne marche pas.
Je ne l'avais pas précisé mais j'ai en effet déroulé "Détails" dans la boite de dialogue. Mais au lieu d'avoir des détails, j'ai un message me disant que AutoCAD ne supporte pas le "débogueur" JIT:
Application does not support just-in-time (JIT)
debugging. See the end of this message for details.
Je me suis renseigné et j'ai installé accessDatabaseEngine mais ça ne change absolument rien.
J'ai donc tenté d'améliorer mon code en suivi vos conseils et voilà ce que ça donne:
Le soucis c'est que ça ne change rien. Lorsque je lance mon programme, une fenêtre d'affiche avec un bouton (jusqu'ici tout va bien) et lorsque je clique sur le bouton, la boite de dialogue d'erreurs s'affiche. Je n'ai pas d'autres messages.

Lien permanent Réponse de gile le 7 décembre 2012 à 10:33 Salut,
Il semble que tu n'aies pas bien compris l'usage des try/catch/finally, regarde ce lien.
De même pour using (voir ici), tu n'as pas besoin d'appeler Close() sur dr.
Essaye comme ça, tu auras peut-être plus d'informations sur les erreurs :
OleDbDataReader dr;
using (dr = com.ExecuteReader())
{
while (dr.Read())
{
MessageBox.Show(dr["Nom"].ToString());
}
}
}
catch (InvalidOperationException)
{
MessageBox.Show("La connexion à la base de données est déjà ouverte.");
}
catch (OleDbException ee)
{
string errorMessages = "";
for (int i = 0; i < ee.Errors.Count; i++)
{
errorMessages += "Index #" + i + "\n" +
"Message: " + ee.Errors[i].Message + "\n" +
"NativeError: " + ee.Errors[i].NativeError + "\n" +
"Source: " + ee.Errors[i].Source + "\n" +
"SQLState: " + ee.Errors[i].SQLState + "\n";
}
MessageBox.Show(errorMessages);
}
catch (System.Exception exn)
{
MessageBox.Show(exn.Message);
}
finally
{
cn.Close();
}
}

Lien permanent Réponse de gile le 7 décembre 2012 à 10:46 PS: poster du code sur ce site relève du calvaire, désolé pour le formatage perdu.
Lien permanent Réponse de Maxence DELANNOY le 7 décembre 2012 à 10:47 +1, il faudrait un bouton code dans la barre de formatage...
Lien permanent Réponse de Maxime D le 7 décembre 2012 à 15:38 Bon mise à niveau de try, catch et finally, OK !
Je suis ici:
"La connexion à la base de données est déjà ouverte"
InvalidOperationException: Exception levée en cas d'appel de méthode non valide pour l'état actuel de l'objet. Mais je ne comprends pas quel est le problème. En quoi je fais un appel de méthode non valide?
Lien permanent Réponse de Maxence DELANNOY le 7 décembre 2012 à 15:47 Et bien c'est simple, tu appelles la méthode Open alors que la connexion est déjà ouverte. Open ne doit être appelé qu'une seule fois.
Je comprends pas trop pourquoi tu utilise un champ pour cn, pourquoi n'utilises tu pas une variable locale ? Sinon, tu peux ajouter :
cn.Close();
juste avant ton cn.Open(). C'est un peu bourrin, mais ça te permettra d'avancer.
Lien permanent Réponse de Maxime D le 7 décembre 2012 à 15:59 J'ai tenté la manière trash en plaçant un close avant, mais ça ne change rien, on reste dans l'exception:
catch (InvalidOperationException)
{
MessageBox.Show("La connexion à la base de données est déjà ouverte.");
}
Lien permanent Réponse de Maxence DELANNOY le 7 décembre 2012 à 16:02 Essaie d'appeler Open après la création de ton objet OleDbCommand

Lien permanent Réponse de gile le 7 décembre 2012 à 18:40 N'y a-t-il pas ailleurs dans ton code un autre endroit où la connexion serait ouverte ?
Si ce n'est pas confidentiel, peut-être pourrais-tu poster l'intégralité du code (sauf le code généré automatiquement pas Visual Studio pour les formulaires) ou mettre la solution complète en lien.
© 2013 Créé par AUGIfr