2009-02-27 6 views
7

Ceci est mon premier post sur StackOverflow, donc s'il vous plaît soyez doux ...ADO.NET les meilleures pratiques pour la connexion et DataAdaptor objet Scope

J'ai quelques questions concernant le champ d'objet pour ADO.NET.

Lorsque je me connecte à une base de données, j'utilise généralement le code comme ceci:

OleDbConnection conn = new OleDbConnection("my_connection_string"); 
conn.Open(); 
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn); 
OleDbCommandBuilder cb = new OleDbCommandBuilder(adapter); 
DataTable dt = new DataTable(); 
adapter.Fill(dt); 
conn.Close(); 
conn.Dispose(); 

Disons que je lie le DataTable résultant à un contrôle du réseau et que mes utilisateurs puissent modifier le contenu de la grille. Maintenant, quand mes utilisateurs appuient sur un bouton Enregistrer, je dois appeler ce code:

adapter.Update(dt); 

Voici mes questions:

1) Dois-je conserver l'objet de l'adaptateur que j'ai créé quand je l'origine chargé le datatable, ou puis-je créer un autre objet adaptateur dans l'événement de clic sur le bouton Enregistrer pour effectuer la mise à jour?

2) Si je dois conserver l'objet adaptateur d'origine, dois-je également garder l'objet de connexion disponible et ouvert? Je comprends le modèle déconnecté de ADO.NET - je suis juste confus sur la portée de l'objet quand il est temps de mettre à jour la base de données. Si quelqu'un pouvait me donner quelques conseils sur les meilleures pratiques pour ce scénario, je l'apprécierais grandement!

Merci à l'avance ...

Répondre

3

1) Vous n'avez pas besoin de la même DataAdapter, mais si vous créez un nouveau, il doit utiliser la même requête que sa base.

2) Le DataAdapter ouvrira sa connexion si la connexion est fermée. Dans ce cas, la connexion sera à nouveau fermée une fois l'opération terminée. Si la connexion est déjà ouverte, la connexion restera ouverte même après l'opération.

Normalement, vous travailleriez comme dans votre exemple. Créez une Conneciton et un DataAdapter, remplissez un DataTable et disposez ensuite de la Connection et du DataAdapter.

Deux commentaires à votre code:

  • Vous n'avez pas besoin CommandBuilder ici puisque vous ne faites sélection. Le constructeur de commande n'est nécessaire que si vous voulez générer des instructions Insert, Update ou Delete automatiquement. Dans ce cas, vous devez également définir InsertCommand, UpdateCommand ou DeleteCommand sur le DataAdapter manuellement à partir de CommandBuilder.
  • Deuxième. Au lieu d'appeler Dispose manuellement, vous devez utiliser la clause Using. Cela garantit que vos objets seront éliminés même si une exception est levée.

Essayez de changer votre code à ceci:

DataTable dt = new DataTable(); 
using (OleDbConnection conn = new OleDbConnection("my_connection_string")) 
using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn)) 
{ 
    adapter.Fill(dt);  
} 

Notez que je définis DataTable en dehors des clauses utilisant. Ceci est nécessaire pour s'assurer que la table est dans la portée quand vous quittez les utilisations. Notez également que vous n'avez pas besoin de l'appel Dispose sur le DataAdapter ou l'appel Close sur la connexion. Les deux sont implicitement fait quand vous quittez les utilisations.

Oh.Et bienvenue à SO :-)

+0

Les adaptateurs de données sont capables d'ouvrir implicitement des connexions, maintenant je ne suis pas sûr de le faire dans une instruction using, mais vous ne pouvez pas supprimer la ligne conn.Open() et laisser l'adaptateur dataadaptor ouvrir la connexion. – GordonB

+0

Bon point. Je l'ai même mentionné sous 2). :-) Je vais mettre à jour l'exemple de code –

+0

Can adaptateur de données peut être un bon choix en cas de dumping des millions d'enregistrements (par exemple: 2-3 millions d'enregistrements que j'ai dans mon datatable) dans la base de données ??? –

0

Pour répondre à vos questions:

  1. Idéalement, vous devez conserver le même DataAdapter parce qu'il a déjà effectué son initialisation. Un DataAdapter fournit des propriétés telles que SelectCommand, UpdateCommand, InsertCommand et DeleteCommand qui vous permettent de définir différents objets Command pour effectuer ces différentes fonctions sur la source de données. Donc, vous voyez, le DataAdapter est conçu pour être réutilisé pour plusieurs commandes (pour la même connexion à la base de données). Votre utilisation de CommandBuilder (bien que non recommandée) crée les autres commandes en analysant SelectCommand, vous permettant ainsi d'effectuer des mises à jour, des suppressions et des insertions en utilisant le même CommandBuilder.

  2. Il est préférable d'autoriser DataAdapter à gérer implicitement les connexions de base de données. @Rune Grimstad a déjà élaboré sur ce comportement implicite et il est utile de comprendre cela. Idéalement, les connexions devraient être fermées dès que possible.

0

Deux détails supplémentaires méritent d'être ajoutés à l'excellente réponse de Rune Grimstad. Tout d'abord, le CommandBuilder implémente IDisposable (si nécessaire) et doit donc être enveloppé dans sa propre instruction 'using'. Étonnamment (au moins pour moi), la disposition du DataAdapter ne pas apparaît pour Disposer le CommandBuilder associé. Le problème que j'ai observé quand j'ai échoué à faire ceci était que même si j'ai appelé Dispose sur le DataAdapter, et l'état de connexion était fermé, je ne pouvais pas enlever une base de données temporaire une fois que j'avais utilisé CommandBuilder pour mettre à jour cette base de données. Ensuite, l'instruction "... Dans ce cas, vous devez également définir manuellement InsertCommand, UpdateCommand ou DeleteCommand sur le DataAdapter ..." n'est pas toujours correct. Pour de nombreux cas triviaux, CommandBuilder crée automatiquement les instructions INSERT, UPDATE et DELETE correctes en fonction de l'instruction SELECT fournie au DataAdapter et des métadonnées de la base de données. «Trivial», dans ce cas, signifie que seule une table unique est accédée et que cette table a une clé primaire qui est retournée dans le cadre de l'instruction SELECT.