Mise à jour Dataset depuis dataGridView + rowFilter
brixi69
Messages postés44Date d'inscriptionmardi 13 juin 2006StatutMembreDernière intervention31 mars 2008
-
22 févr. 2008 à 09:43
Arthenius
Messages postés1182Date d'inscriptionmercredi 21 janvier 2004StatutMembreDernière intervention 6 septembre 2011
-
16 sept. 2008 à 18:15
Bonjour !
J'ai beau chercher je ne parviens pas à trouver une solution à mon problème et j'espère que quelqu'un pourra "lairer ma lanterne.
J'ai un dataGridView dont le dataSource est lié à un dataSet.
Lorsque j'effectue des modifications directement dans le dataSet le dataGridView est automatiquement mis à jour.
Par contre lorsque j'effectue des modifictations dans le dataGridView le dataSet ne prend pas directement en compte les modifs.
Je m'explique.
La table liée au dataGridView contient une colonne avc une valeur booléenne.
Admettons que j'ajoute un rowFilter sur mon dataSet pour ne filtrer que les lignes ayant une valeur = 1. Le dataGridView est bien mis à jour avec uniquement les lignes ayant la valeur 1. Par contre si je met ma valeur à 0 pour une ligne du dataGridView et valide, la ligne ne disparait que quand elle perd le focus. J'aimerais savoir comment forcer la mise à jour du dataSet sur base du dataGridView afin que le dataGridView soit mis à jour directement en tenant compte du rowFilter et que cette ligne disparaisse.
J'espère avoir été clair.
Un grand merci d'avance...
@"#+++
brixi69
Messages postés44Date d'inscriptionmardi 13 juin 2006StatutMembreDernière intervention31 mars 2008 28 mars 2008 à 09:44
Oui j'ai vérifié. Le problème se pose pour des lignes qui viennent d'être ajoutées.
1. J'ajoute une nouvelle ligne à mon dataSet et ca se répercute sur le DGV. L'état est "added"
2. Je modifie la ligne dans mon DGV et ca se répercute sur le dataSet. Toutefois l'état reste "added" et l'édition n'est pas prise en compte dans les opérations à effectuer lors de l'update.
Le problème est peut-être lié au fait que je travaille une fois directement dans le dataSet (ajout) et l'autre fois dans le DGV (edition)
ecosmose
Messages postés46Date d'inscriptionvendredi 5 novembre 2004StatutMembreDernière intervention30 septembre 2010 28 mars 2008 à 14:10
Bonjour,
Il apparait clairement que ta méthodologie de mise à jour depuis l'adapter n'est pas bonne je rappele d'abord ton extrait de code (sur les pages précédents ) puis je m'explique...
private void do_UpdChauf()
{ MySqlCommandBuilder cb = new MySqlCommandBuilder(adaChauffUpd);
DataSet ch = new DataSet();
if (null != ch)
{
int del = adaChauffUpd.Update(ch);
}
ch = dsChauffUpd.GetChanges(DataRowState.Modified);
if (ch != null)
{
int upd = adaChauffUpd.Update(ch);
}
etc...
La méthode Update() d'un Adapter utilise des Command pour mettre à jour en Base (DBCommand : méthodes SQL ou Procédure stockées d'insert, de delete et de Update ) générées dans le designer de Visual (des Tableadapter et du Dataset) ce qui est apparement ton cas, soit des 'Commands personnalisées'. Tu peux retrouver l'assignation des Commands dans la fichier InitAdapter() du fichier designer de ton dataset (attention à ne pas modifiés car il est regénéré à chaque modif ) La méthodologie que tu emploies pourrais se résumer à ce code..
private void do_UpdChauf()
{
MySqlCommandBuilder cb = new MySqlCommandBuilder(adaChauffUpd);
DataSet ch = new DataSet();
//récupération de tous les changements
ch = dsChauffUpd.GetChanges();
if (null != ch)
{
int del = adaChauffUpd.Update(ch);
}
etc...
Le décisionnel des Commands à executer est géré par les RowStates (Added, Modified etc) qui vont déclenché les COmmands correspondantes (INSERT, UPDATE etc...). ces méthodes sont traitées ligne par ligne au sein d'une transaction...(d'où un Rollback de toutes les Rows ajoutées , modifiées ou supprimées en Base
Le problème est que certains Adapters (comme le DataAdapter qui est une classe mère de TableAdapter) possèdent des arguments par défauts tels que
AcceptChangesDuringFill = true;
AcceptChangesDuringUpdate = true;
ou encore ClearBeforeFill = true;
Ce qui réinitialise les états des rows à Unchanged dès la fin de la méthode Update()...
Tel un DataRow.AcceptChanges();
Si tu souhaite conservés le rowstate APRES mise à jour en base tu dois surcharger ces attributs (dans Dataset.cs)
tu devras ensuite gérer l'invocation du Acceptchanges..ou du RejectChanges que l'on place de manière classique dans la détection d'erreur (try / catch -> avec gestion possible du Rollback..)
En esperant t'avoir éclairci
BINOME de ECOSMOSE
Association ecologique d'actions de culture et d'Informations
brixi69
Messages postés44Date d'inscriptionmardi 13 juin 2006StatutMembreDernière intervention31 mars 2008 28 mars 2008 à 16:01
Merci pour ces explications qui éclaircisent effectivement encore un peu plus mon esprit quant aux méthodes à utiliser et à leur fonctionnement général.
Toutefois je ne pense pas que cela me permette de résourdre mon problème.
Pour rappel : l'ajout d'une ligne dans mon dataSet ajoute bien une ligne à la liste des opérations à effectuer sur la bdd, liste d'opérations que je peux obtenir avec la méthode getChanges. Cette opération possède le rowState "added".
Par contre lorsque j'édite ensuite cette même ligne (en passant par le DGV), le dataSet est bien modifié à son tour puisqu'il est lié mais l'opération n'apparait pas dans la liste des opérations à effectuer, liste que je peux obtenir avec la méthode getChanges.
On ne peut donc pas gérer plus d'une opération par ligne?
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20106 28 mars 2008 à 16:45
Merci a ecosmose d'apporter quelques eclaircissement pratique concernant le concept de gestion des flags APRES l'update
brixi69 resitue son problème d'etat du flag AVANT l'update
Mais il me semble qu'il y a toujours un malentendu concepuel
Il est normal qu'un row ajouté ait le statut Added et tant qu'il n'est pas sauvé dans la DB il restera added meme su tu le modifie : pratiquement c'est toujours un row a ajouter !!
Donc si apres l'avoir ajouté tu effectue des modification dedans AVANT de le sauver le statut restera added et c'est logique
Autre point d'attention lié a cette logique !
SI ta table contient une key autoincrement
ATTENTION : lorsque tu ajoute un row a ta datatable, la key restera nulle sa valeur sera attribuée par le DBE lors de l'update effectif.
MAIS !! Cette valeur ne sera pas automatiquement répercutée dans le dataset
Donc si apres tu essaye de modifier ou supprimer ce row, tu te ramasse un message d'erreur ésotherique car la clef que tu passe est toujours nulle !
La maniere la plus efficace que j'ai trouvé pour eviter ce probleme, c'est de faire l'update et puis en clear et un fill du dataset (dans le cas ou j'ai des autoincrement)
ecosmose
Messages postés46Date d'inscriptionvendredi 5 novembre 2004StatutMembreDernière intervention30 septembre 2010 28 mars 2008 à 19:27
Ok recu pour la problématique ...
Je pensais que mes explications auraient fixées le fait que lorsqu''une Row est créée, elle aura toujours le Rowstate Added tant qu'elle n'est pas insérée dans la base...L'avantage du Dataset dans ce cas de figure est les Datarelations...car le client dispose du schéma relationnel de la base et peut aisément travailler (en déconnecté) sur des Entités (par ex des Row Added) qui ne sont pas en Base et attaché des Entités enfants à cette Entité...Les datarelations permettent ensuite de conserver le relationnel lors de mise à jour en base tout en resolvant les problèmes de AutoIncrement de Primary Key, ou encore de rafraichir des modifs (en cascade par ex) effectué par un autre client (parenthèse fermée)
pratiquement c'est toujours un row a ajouter !! -> je dirais que c'est logique et obligatoire pour une bonne cohérence ...
Il faudra que [auteur/BRIXI69/799407.aspx brixi69 ] explique les opérations qui sont effectuées entre l'ajout et la modif
Quote [auteur/BRIXI69/799407.aspx brixi69] : "Par contre lorsque j'édite ensuite cette même ligne "
1-Fais tu un ajout en BD puis une modif...(d'après ce que j'ai compris c'est le cas, dans ce cas il faut que tu regarde si la méthode AccepChanges() est invoqué (automatiquement ou non) après l'update cf. mes explications, utilise juste pour vérifier la méthode que je t'ai joint AVANT ET APRES l'update tu seras sur de tes questions ou alors observe avec le debug ce que contient ta row comme tu dois déjà le faire...)
ou 2- La modif est effectuée avant la créatuion de la ligne en Base (cad que la row est crée puis modifiés par le client, puis mise en Base -> dans ce cas nos précédentes explications devraient t'éclairer..)
ou 3- Petite nouveauté, une row n'est pas visible si tous les champs qui possédent des contraintes ne sont pas remplie ou si la row est en cours de création...dans ce cas elle possède le Rowstate Detached (je pense que c'est ce qui se passe pour toi)...et n'est pas visible dans la mémoire (en fait elle est cachée) ...en utilisant les fonctions PrintView que je t'ai posté tu aurais du voir cet état....Si c'est le cas je te conseille vivement de travailler avec des DataView qui permette d'utiliser des données de lignes qui veinnent d'etre créer mais qui ne sont pas encore validée...ainsi tu preserve tes relations intertable MAIS tu ne te restraint pas aux contraintes techniques du Dataset ...de même je te conseille de désactiver les contraits (EnforceConstraintes = false) lorsque le client travaille avec ces IHM sur le Dataset...active les uniquement en cas de Validation ou quand le client s'(apprete à interogger la BD...
Voila , tu penses bien que ces infos ont du vécu et que le Framework Microsoft est à leur image..no comment
BINOME de ECOSMOSE
Association ecologique d'actions de culture et d'Informations
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20106 28 mars 2008 à 21:32
J'aime beaucoup la precision et l'aspect didactique de tes explications ecosmose Attention je vais te garder sous la main pour le prochain noeud que j'aurai a affronter en traitement DB
Je n'ai jamais travaillé avec les datarelation : a investiguer
Par contre, j'ai découvert récemment la methode select d'une datatable
Elle m'a permis de contourner un GROS problème aussi rencontré avec le DGV
Si tu trie un DGV sur une colonne par programation et meme si le DGV est notsortable il devient impossible d'empecher le tri automatique de ce DGV
Catastrophe evidement si comme brixi69 tu effectue des manip par programmation sur cette colonne.
Pour contourner ce probleme j'ai utilisé un select comme décrit ci dessus qui me permet de definir un odre et d'acceder directement a la datatable suivant cet ordre sans passer par le DGV qui lui se met a danser la Java !
ecosmose
Messages postés46Date d'inscriptionvendredi 5 novembre 2004StatutMembreDernière intervention30 septembre 2010 29 mars 2008 à 00:17
Simple idée : As tu penser à utiliser des DataView des DataTables d'exploitations ?
J'utilise un autre outil pour la GUI (Graphis User Interface mes IHM..) c'est DevExpress qui utilise des GridViews...il me semble (c'est sur pour DevExpress,DGV je ne sais pas) que ces deux 'tableurs' utilise une BindingSource (=DataTable) ce qui leur permet de se lier (to bind en anglais) à la source de données....
Or Je pense que tu devrais dissocier Les données présentés (Businness Object, les objets de travail donc d'IHM) et les données 'brutes' utilisées par la DAL...D'ailleurs la logique relationnel dans le mode déconnecté n'est souvent pas la même (entre le client et le serveur)..
Donc utilises des unions de DataView pour les BO ...à noter que les dataview sont aux DataTabbles ce que sont les vues d'un SGBD aux Tables d'une Base de données...ce sont des cartographie de pointeurs qui ne contiennent que les adresses mémoires des données...donc quand tu modifies une vues tu mosdifies un datatables...regarde aussi les options de tri, de filtre qui te faciliteront grandement les gestions des vues IHM par programmation...y'a aussiles DatarowsState qui sont interessante et le fait que tyu puisses acceder aux données des Rows qui sont detached (contrainte vue ci - dessus..)
Au plaisir de t'aider une prochaine fois (hesite pas à envoyer un mail)
BINOME de ECOSMOSE
Association ecologique d'actions de culture et d'Informations
brixi69
Messages postés44Date d'inscriptionmardi 13 juin 2006StatutMembreDernière intervention31 mars 2008 29 mars 2008 à 10:33
Et bien je ne suis pas mécontent d'avoir mis ce post ne serait-ce que pour en avoir appris autant. Merci à tous les deux ;-)
Je vais résumer mon problème en essayant de lier avec ce que vous venez de m'indiquer.
1.
Lors du démarrage du programme mon DATASET est rempli à partir de la BDD.
Lors de la fermeture du programme (et uniquement à ce moment) ma BDD est mise à jour à partir du DATASET.
Par conséquent tous mes problèmes se trouvent effectivement AVANT (merci Olibara) l'update de la BDD puisque toutes mes opérations se font en mode "déconnecté".
2.
Un DATAGRIDVIEW est alors lié à ce DATASET. Toutes les données ne sont pas toutjours visibles dans le DATAGRIVIEW car je filtre mon DATASET (defautView.rowFilter).
3.
Le type d'opération effectué est effectivement celui précisé dans ton point 2 "Ecosmose".
J'ajoute une ligne au DATASET directement (monDataSet.add...) (rowState = "added").
La ligne apparait dans le DATAGRIVIEW lié.
J'édite un des champs dans le DATAGRIVIEW. La modification ce répercute dans le DATASET . le rowState reste "added" effectivement c'est logique. Toutefois lorsque je liste les changements à effectuer avec getChanges() le champ modifié dans le dataSet n'est pas modifié.
Un petit exemple vaut mieux qu'un long discours avec les opérations intermédiaires effectuées et les états.
//Ouverture du programme
monDataSet = monDataAdapter.GetData();
//Le DGV contient toutes les lignes de la bdd. J'en ajoute une en passant par le dataSet. Celle-ci est ajoutée par lien au DGV.
monDataSet.AddRow("NouveauNom1", ..., ..., );
// ==> valeur de la cellule nom dans le DGV = "NouveauNom1"
// ==> valeur de la cellule nom dans le DATASET = "NouveauNom1"
// ==> valeur de la cellule nom dans le GETCHANGES = "NouveauNom1"
//Edition de la cellule "nom" par simple clic dans le DGV. La cellule est modifiée par lien dans monDataSet.
//"NouveauNom1" ==> "NomModifié1"
// ==> valeur de la cellule nom dans le DGV = "NomModifié1"
// ==> valeur de la cellule nom dans le DATASET = "NomModifié1"
// ==> valeur de la cellule nom dans le GETCHANGES = "NouveauNom1"
//Application d'un filtre sur les données visibles dans le DGV. La ligne ajoutée n'est PAS visible expressément.
monDataSet.DefaultView.RowFilter = ...;
// ==> valeur de la cellule non visible dans le DGV
// ==> valeur de la cellule nom dans le DATASET = "NomModifié1"
// ==> valeur de la cellule nom dans le GETCHANGES = "NouveauNom1"
//Ajout d'une ligne au DGV (donc visible avec le filtre) en passant par le dataSet
monDataSet.AddRow("NouveauNom2", ..., ..., );
// ==> valeur de la cellule nom dans le DGV = "NouveauNom2", la première n'est pas visible à cause du filtre
// ==> valeur de la cellule nom dans le DATASET = "NouveauNom2" et "NomModifié1"
// ==> valeur de la cellule nom dans le GETCHANGES = "NouveauNom2" et "NouveauNom1"
//Edition de la cellule "nom" par simple clic dans le DGV. La cellule est modifiée par lien dans monDataSet.
//"NouveauNom2" ==> "NomModifié2"
// ==> valeur de la cellule nom dans le DGV = "NomModifié2", la première n'est pas visible à cause du filtre
// ==> valeur de la cellule nom dans le DATASET = "NomModifié2" et "NomModifié1"
// ==> valeur de la cellule nom dans le GETCHANGES = "NouveauNom2" et "NouveauNom1"
//Je quitte le programme après avoir enlever le filtre puis mis à jour en bdd.
monDataSet.DefaultView.RowFilter = "";
// ==> valeur de la cellule nom dans le DATASET = "NomModifié2" et "NomModifié1"
// ==> valeur de la cellule nom dans le GETCHANGES = "NomModifié2" et "NouveauNom1"
monDataAdapter.update(monDataSet);
//FIN
Voilà je ne saurais être plus précis. Si vous n'avez pas d'idées je me contenterai de ma technique qui fonctionne
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20106 29 mars 2008 à 12:31
Salut
Il y a quand meme un truc qui me chiffone c'est que la methode AddRow que tu mentionne
N'est ni membre de DataSet ni de DataTable ni de datagridview
Du moins dans csharp 2008 framework 3.5
Si c'est bien un AddRow que tu fais, c'est sur quel type d'objet ?
ecosmose
Messages postés46Date d'inscriptionvendredi 5 novembre 2004StatutMembreDernière intervention30 septembre 2010 29 mars 2008 à 18:07
Re !
Je confirme que la fonction AddRow n'existe pas sur le DataSet (logique sinon sur quelle DataTable pointée, raisonnement par l'absurde -> donc pas possible)...
tu utilises donc des DataTables dont l'une s'appele 'categories'... je te réitère le conseil d'attacher une DataView à la DGV...et je serais curieux de savoir comment tu attaches ce dataset à la DGW ...la bonne logique est présentée comme ceci :
Categorie_list = new CategorieDataTable();
//Ouverture du programme
monDataSet = monDataAdapter.GetData();
DGV.DataSource = monDataSet.defaultViewManager;
ce qui apparement est ton besoin...regarde aussi les attributs par defaut de la defaultview... et le mécansime d'une datasource de DGV
brixi69
Messages postés44Date d'inscriptionmardi 13 juin 2006StatutMembreDernière intervention31 mars 2008 31 mars 2008 à 10:05
Désolé sur ce coup là j'ai manqué de précision. C'est effectivement une table appartenant à un dataSet que je lie. Je pensais que vous l'aviez compris. Dans mon code précédent vous pouvez prendre tous les monDataSet pour des monDataTable. On ne peut pas lié un dataset complet à un dataGridView? si?
j'ai sinon pour ma part :
bddDepensesDataSet.CategoriesDataTable
categories_list = new bddDepensesDataSet.CategoriesDataTable();
pour l'ajout d'une ligne au dataTable (les paramètres correspondent aux colonnes)
Je vais jeter un oeil du côté du dataRowViewState pour le filtre car effectivement ca ne m'a pas tracassé.
Je vais également testé un bindingSource avec resetItem pour voir si ca peut fonctionner.
Je vous tiens au courant plus tard car ceci est un passe-temps et la semaine je n'ai pas vraiment le temps.
ecosmose
Messages postés46Date d'inscriptionvendredi 5 novembre 2004StatutMembreDernière intervention30 septembre 2010 31 mars 2008 à 19:37
Pour info, Une datasource implémente déjà l'interface IBindingSource...as tu essayé de travailler avec les DataViews alors ? il me semble que à défaut le DGV travaille avec le defaultview des DaTatables...méfie toi aussi des rafraichissements des dataview qui interviennent lors de la modification et de la suppression de rows (ATTENTION si tu as une trop grosse table préfère la datatble car les opérations de rafraichissement ont un ordre o(n))...
Bon codage
BINOME de ECOSMOSE
Association ecologique d'actions de culture et d'Informations
Arthenius
Messages postés1182Date d'inscriptionmercredi 21 janvier 2004StatutMembreDernière intervention 6 septembre 201114 16 sept. 2008 à 18:15
je suis tomber par hasard sur cet discussion,
je vous met un lien vers un de mes sources qui aurait pu aider...
le currencymanager qui gere tres bien les pb de binding que tu semble avoir eu...