Slt à tous,
Quelqu'un saurait-il comment on récupère un champ "auto-increment" lors d'une requete d'insertion dans une table via ADO.NET?
Merci d'avance.
Slt à tous,
Quelqu'un saurait-il comment on récupère un champ "auto-increment" lors d'une requete d'insertion dans une table via ADO.NET?
Merci d'avance.
avec une requête qui va dépendre du SGBD
Elle est où la portabilité sous ADO.NET s'il faut modifier le code pour une fonctionnalité au moins aussi basique que fréquemment utilisée?
Est ce que je pourrais avoir un exemple sous un SGBDR de ton choix (de préférence Access,SQl Server ou MySQL qui sont installés sur ma machine)?
Merci pour ta réponse
Si tu veux de la portabilité, tu ne fais pas ta requete dans le code. Tu fais une procédure stockée qui te renvoie l'identifiant.
Sinon la récupération dépend de ton SGBD.
Sous SQL Server il fait utiliser la fonction SCOPE_IDENTITY( ) : ( SELECT SCOPE_IDENTITY() ).
Sous Oracle les champs auto incrémenté n'existent pas (je dis pas de connerie là ?) c'est remplacé par des séquences.
Les règles du forum
Le trio magique : FAQ + Cours + fonction rechercher
Mes articles
Pas de questions par messages privés svp
Software is never finished, only abandoned.
Franchement elle est bonne celle là. Comme si c'était la faute d'ADO.NET si le jeu préféré des éditeurs de SGBD est d'implémenter chacun des langages à la con plutôt que de suivre les normes SQL...
On peut simuler les auto increments sous Oracle avec une séquence associé à un TRIGGER.Sous Oracle les champs auto incrémenté n'existent pas (je dis pas de connerie là ? ) c'est remplacé par des séquences.
Je pense pouvoir avancé avec peu de risque de me tromper que pratiquement tous les SGBDR (corrige moi si je me trompe) dispose de cette fonctionnalité sous des noms ou sous des formes différentes. ce qui fait qu'en Java, sous JDBC, il existe une fonctionnalité standard permettant de récupérer ce type de champ (il s'agit de la méthode getGeneratedKeys() de l'interface Statement)! Libre au Driver utilisé de récupérer la bonne valeur.Franchement elle est bonne celle là. Comme si c'était la faute d'ADO.NET si le jeu préféré des éditeurs de SGBD est d'implémenter chacun des langages à la con plutôt que de suivre les normes SQL...
Et on ne peu pas dire que .NET, comparé à JAVA, soit un modèle de portabilité!
oui, l'ancienne version d'ADO en avait une aussi, qui posait plus de problème qu'elle n'en résolvait d'ailleurs ce qui est aussi le cas de getGeneratedKeys.
Quelle est l'intérêt d'utiliser une méthode qui renverra potentiellement n'importe quoi si le fournisseur ne la gère pas ???
La programmation 'générique' des SGBD restera toujours une légende tant que la norme SQL ne sera pas strictement respectée par la plupart des SGBD.
Je pense que la plupart des SGBDR respectent la norme (je dis bien la plupart parce que ce n'était pas le cas de MySQL par exemple pendant un bon moment), mais rejoutent à celle-ci des fonctionnalités pour rendre leur produit plus séduisant! Libre à nous de limiter notre utilisation de SQL trictement à la norme ANSI.
Il demeure vrai que s'ils se limitaient tous trictement à SQL ANSI, la vie serait plus facile pour tous, mais c'est la une vision pour le peu utopique!
En ce qui concerne getGeneratedKeys(), il est vrai que certains pilotent JAVA ne l'implémentent pas (par exemple le pilote ODBC si ma mémoire est bonne), mais ceux qui l'implémentent ne renvoient pas "n'importe quoi" comme tu dis.
Quoi qu'il en soit, je pense que ce type de fonctionnalité est indispensable dans une bonne conception et je trouve dommage que ce ne soit pas un standard SQL.
Reste à savoir de quelle norme on parle, car la plupart respecte SQL2 mais pas les versions suivantes, ce qui est une approche quand même un peu minimaliste.
Si ADO.NET n'implémente pas de méthode générique de récupération de clé alors que ADO le faisait, c'est bien parce que potentiellement cela renvoie une valeur erronée. Dans le principe couramment admis, c'est la procédure SGBD qui doit renvoyée la clé et non une requête postèrieure à la procédure d'insertion. Car dans un contexte multi utilisateurs, il existe rarement la garantie qu'il n'y aura pas eu un autre enregistrement ajouté et donc une erreur dans la clé récupérée. A mon sens, les méthodes comme getGeneratedKeys ou UpDateResync sont des faux amis car il masque le code SQL de récupération effectivement envoyé et donc les erreurs potentielles que celui ci peut contenir ou engendrer.
Si nous sommes bien d'accord avec le fait qu'un champ incrémenté comme identifiant d'une table est une bonne conception, comment me conseillerais tu donc d'implémenter cette fonctionnalité tout en restant indépendant du SGBDR?
Recharger partiellement les tables, c'est à ma connaissance le seul moyen universel de récupérer les bonnes valeurs à coup sur
ç'est à dire? Qu'est ce tu entends par "recharger partiellement les tables"?Recharger partiellement les tables, c'est à ma connaissance le seul moyen universel de récupérer les bonnes valeurs à coup sur
J'entends faire un Fill de toutes les tables ayant eu des Insert au moins à partir du dernier numéro de clé originale en désactivant les contraintes.
Fondamentalement, le problème des clé auto générés dans une application est double, il n'est pas évident de récupérer le bon numéro de clé et les enregistrements liés doivent mettre à jour la clé étrangère correctement aussi, sauf si on fait une mise à jour partielle entre la création du parent et celle des enfants.
Pour contourner ce problèmes, on donne au niveau du Dataset des clés négatives pour être sur de ne pas avoir de collision, en désactive EnforceConstraint, on envoie la ou les mise(s) à jour, on recharge la ou les table(s), on effectue un rejectChanges sur les lignes ajoutées pour supprimer les enregistrements à clé négative et on rétablit EnforceConstraint.
Si les tables sont petites, pas de problèmes pour recharger toute la table, mais si tu as des dizaines de milliers d'enregistrement, c'est vite l'usine à gaz. Dans ce cas, on recharge la table en utilisant une requète avec un prédicat restrictif sur la clé.
Par exemple supposons que lors du premier chargement (donc avant les modifs) ta table contenait les enregistrement jusqu'à la clé 152321, on refait un Fill avec une requête du genre Select * From Table Where Id>152300
Je sais c'est un peu lourd, mais c'est la seule méthode universelle fiable
oui mais s'il n'utilise pas de dataset ?
Les règles du forum
Le trio magique : FAQ + Cours + fonction rechercher
Mes articles
Pas de questions par messages privés svp
Software is never finished, only abandoned.
la démarche reste la même, l'objet de stockage est sans importance
C'est le cas de le dire. J'utiliserais très bientot .NET dans un domaine ou la séparation en 3 couches est primordiale et ou la gestion de la concurrence d'accès doit être optimale. dans ces conditions la, je ne pense pas que les DataSet soient la solution à adopter. Compte tenu du fait que je vais utilisé plutot ADO.NET en mode connecté, que pensez vous de faire dans une même transaction ou dans un batch de requêtes:Je sais c'est un peu lourd, mais c'est la seule méthode universelle fiable
initialiser l'id à 1 si on a aucun résultat, et puis faire notre requete d'insertion?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 SELECT MAX(ID)+1 FROM MyTABLE
Partager