none
WPF - ADO.NET : Effacement des commandes à la consolidation :7 RRS feed

  • Question

  • VS2015 - WPF - ADO.NET - ACCESS

    Je fais face à un comportement anormal lorsque j'enregistre des commandes d'un client dans une relation Maître/Détail au travers de deux DataGrid.

    Lorsque je saisis un client sur la dernière ligne vide du contrôle DataGrid Maître, ensuite je saisis une commande de ce client dans le DataGrid Détail sur la dernière ligne de ce contrôle, et que je clique sur le bouton d'enregistrement, pendant la phase de consolidation dans la source de données, l'application efface le contenu du contrôle détail alors que la vue de la table des commandes a bien pris en compte la commande que je viens d'enregistrer.
    Si je relance l'application et que je me positionne sur le client que je viens de rentrer, la commande apparaît bien dans le DataGrid des commandes.

    J'ai tracé le parcours en phase de consolidation et m'aperçois que l'anomalie est liée à la fonctionnalité de mise à jour des clés étrangères des enregistrements du DataTable Commandes lorsque la numérotation automatique du client est effectuée dans l'évènement RowUpdated du Datable Clients. La propriété de la relation est Update Cascade.

    Avant lancement de la consolidation
    Nom : Capture Avant.PNG
Affichages : 0
Taille : 18,1 Ko

    Pendant
    Nom : Capture Pendant.PNG
Affichages : 0
Taille : 31,2 Ko

    Après consolidation
    Nom : Capture Apres.PNG
Affichages : 0
Taille : 18,1 Ko

    Je ne sais vraiment pas comment régler ce problème et cela fait quelques jours que je cherche désespérément. Je suis tombé sur des liens sur internet qui en parlent mais sans solution :
    https://stackoverflow.com/questions/...-from-datagrid
    https://connect.microsoft.com/Visual...-binding-issue

    Chose encore plus bizarre, lorsque je saisis un nouveau client et que je l'enregistre d'abord dans un premier temps, puis ensuite je saisis une commande, la colonne de clé étrangère de l'enregistrement Commande est initialisée de manière erronée avec une numérotation auto incrémentée, alors qu'elle devrait reprendre la valeur de la clé primaire de l'enregistrement Client. Mais bon, cela est un autre problème mais qui pourrait être cependant lié au premier.

    Aussi, je me permets de vous indiquer un lien de téléchargement de mon projet WPF pour éventuellement que vous puissiez reproduire le comportement et éventuellement m'aidez à résoudre ce problème qui est très bloquant pour moi et le projet sur lequel je travaille.

    https://drive.google.com/file/d/0B64...ew?usp=sharing

    Merci d'avance de votre aide
    .
    mercredi 14 juin 2017 23:54

Toutes les réponses

  • Bonjour,
    Je souhaiterais corriger un point de mon post concernant la numérotation automatique du client qui est plutôt effectuée dans l'évènement RowUpdated du [I][B]TableAdapter[/B][/I] du DataTable Clients. La relation entre deux tables Clients et Commandes inclue la contrainte de clé étrangère et prévoie les règles Update Cascade, Delete Cascade et Accept/Reject None.

    le code de la méthode RowUpdated est :

            private void dataadapterClients_RowUpdated(object sender, OdbcRowUpdatedEventArgs args)
            {
                if (args.RecordsAffected > 0)
                {
                    if (args.StatementType == StatementType.Insert)
                    {
                        Console.WriteLine("[DBWpf, ClientsTableAdapter] dataadapterClients_RowUpdated, Attibue un numero d'ordre au client nouvellement cree");
    
                        OdbcCommand cmdIdentity = new OdbcCommand("SELECT @@IDENTITY", args.Command.Connection);
                        cmdIdentity.Transaction = Transaction;
                        Console.WriteLine("[DBWpf, ClientsTableAdapter] dataadapterClients_RowUpdated, Avant numerotation automatique du client");
                        int id = (int)(cmdIdentity.ExecuteScalar());
                        Console.WriteLine("[DBWpf, ClientsTableAdapter] dataadapterClients_RowUpdated, Client_ID : " + id);
                        args.Row.Table.Columns["Client_ID"].ReadOnly = false;
                        args.Row.Table.DataSet.Tables["Commandes"].Columns["Client_ID"].ReadOnly = false;
                        MessageBox.Show("Stop ??????????????????");
                        args.Row["Client_ID"] = id;
                        args.Row.Table.Columns["Client_ID"].ReadOnly = true;
                        args.Row.Table.DataSet.Tables["Commandes"].Columns["Client_ID"].ReadOnly = true;
                        Console.WriteLine("[DBWpf, ClientsTableAdapter] dataadapterClients_RowUpdated, Apres numerotation automatique du client");
                    }
                    if (args.StatementType == StatementType.Insert || args.StatementType == StatementType.Update)
                    {
                        Console.WriteLine("[DBWpf, ClientsTableAdapter] dataadapterClients_RowUpdated, Recuperation de l'horodatage de la ligne client. Type d'ordre : " + args.StatementType);
    
                        int intCriteria = 0;
                        if (args.StatementType == StatementType.Insert)
                            intCriteria = (int)args.Row["Client_ID"];
                        else
                            intCriteria = (int)args.Row["Client_ID", DataRowVersion.Original];
                        OdbcCommand cmdStamp = new OdbcCommand("SELECT Stamp FROM Clients WHERE Client_ID = " + intCriteria, args.Command.Connection);
                        cmdStamp.Transaction = Transaction;
                        Console.WriteLine("[DBWpf, ClientsTableAdapter] dataadapterClients_RowUpdated, Avant ExecuteScalar");
                        DateTime dteStamp = (DateTime)(cmdStamp.ExecuteScalar()); // DateTime.Now
                        Console.WriteLine("[DBWpf, ClientsTableAdapter] dataadapterClients_RowUpdated, Horodatage : " + dteStamp);
                        args.Row.Table.Columns["Stamp"].ReadOnly = false;
                        args.Row["Stamp"] = dteStamp;
                        args.Row.Table.Columns["Stamp"].ReadOnly = true; // true
                    }
                }
                else
                {
                    // args.Row.RowError = "Conflit d'acces concurrentiel optimiste rencontre"; // Concurrency Violation Encountered
                    // args.Status = UpdateStatus.SkipCurrentRow;
                }
            }
    
    

    J'ai donc une forte présomption que l'anomalie proviendrait de l'instruction située juste après le MessageBox.Show() qui initialise l'ID du client et propage la mise à jour (Update Rule Cascade) aux enregistrements enfants correspondant aux commandes du client (une seule commande dans le cas de l'exemple de mon post) :

    MessageBox.Show("Stop ??????????????????");
    args.Row["Client_ID"] = id;




    Le mécanisme de liaison "TwoWay Binding" de WPF devrait assurer la mise à jour de l'UI, mais dans le cas présent, je fais face à un effacement du DataGrid des commandes bien de la ligne de la commande ait été ajoutée à la table Commandes du Dataset ????



    Est-ce que quelqu'un pourrait m'expliquer ce que j'aurais oublié de faire pour que cela fonctionne correctement ?

    Merci d'avance
    .


    • Modifié rbmoman vendredi 16 juin 2017 15:12
    vendredi 16 juin 2017 15:01
  • Je n'ai toujours pas réussi à trouver une solution mon problème de non affichage des enregistrements à l'issue d'une saisie sur la dernière ligne vide du DataGrid Détail.
    Je désespère...
    Merci à toute âme charitable qui pourrait m'aider à le résoudre
    .

    • Modifié rbmoman dimanche 18 juin 2017 18:41
    dimanche 18 juin 2017 18:38
  • Bonjour la communauté,
    Ce lien concernant les derniers développements relatifs à l'objet de mon feedback au Support Microsoft : https://connect.microsoft.com/VisualStudio/feedback/details/3136661/ado-net-master-detail-wpf-detail-datagrid-erased-on-rowupdated-event

    De l'aveu même des ingénieurs du support technique, il s'agit belle et bien d'un bug WPF - ADO.NET datant d'il y a au moins 7 ans, qui a été partiellement corrigé au niveau des API ADO.NET en 2011 dans la version 4.5 du .NET Framework, mais pas du tout du côté des API WPF car non visé dans le workflow de validation des corrections de bugs. De plus, ils vont devoir reprendre les investigations depuis le début en raison de la perte des tests unitaires entrepris entre temps.

    Mais bon, cela ne règle en rien mon problème immédiat. j'attends encore qu'ils me proposent une solution de contournement réalisable sans trop de pirouettes abracadabrantes.

    Que va donc être l'issue de ce bug ?
    Est-ce que les ingénieurs de Microsoft comptent le fixer dans les prochaines mises à jour du Framework. Pour la 4.7, c'est acquis il est déjà trop tard.
    Pour ma part, je pense que Microsoft devrait absolument régler ce bug dans une certaine mesure, parce qu'il en va de la crédibilité de tout le Framework d'accès aux données ADO.NET et de toute la mécanique de liaison du WPF. Sans une correction adéquate, l'ensemble de l'API est sans aucun intérêt, on peut le prendre et le jeter à la corbeille (Il faudra qu'elle soit bien grande). Et je ne parle même pas de l'expérience utilisateur pour être dans le vent.
    Quelle va être la deadline pour une résolution ?

    Pour seule indication encourageante, ils rajoutent à la fin de leur réponse : "You may receive a general 'Feedback Item Updated' notification as well, if any other changes were made by Microsoft".
    J'aime beaucoup la petite nuance conditionnelle du "if".

    Après 7 longues bonnes années d'attente, Il est urgent d'attendre encore
    La suite des évènements au prochain épisode

    Raymond

    GMT-10, Jeudi 13/07/2017
    Réponse du Support Microsoft : The WPF team will look at fixing this in a future release. When it's fixed, we'll reply to this thread. Given the current backlog and release schedules, the best estimate would be roughly a year from now.
    Commentaire : Minimum 1 an d'attente pour la correction du bug WPF. Fidèle au précepte d'Auguste, on inscrira la devise ci-après au nom de Microsoft : "Hâte-toi lentement"

    Ma réponse au support :
    Thank you for having planned a fix to this bug problem, despite the estimated calendar of a year which is quite long I find. Would it not be possible to settle it more quickly?
    The prerequisites for my IT development projects depend on it. Because of this bug, I am unable to deliver them on time and see myself probably having to pay penalties.

    What could be the workaround to the specific case of the bug so that I can continue my projects, deliver them on time and avoid loosing money?

    I would greatly appreciate your assistance in setting up a temporary workaround base on my test project downloadable at this web address: https://drive.google.com/file/d/0B64...ew?usp=sharing
    Thank you very much for your help

    .

    • Modifié rbmoman vendredi 14 juillet 2017 02:06
    mercredi 12 juillet 2017 20:27
  • Réponse du Support Microsoft :

    If you have a Premier support contract, you can request a hotfix via your CSS representative. To set expectations, your request would likely be refused on the grounds that the bug has existed for 10 years with only two complaints, and the first complainant (from 2010) went silent and got no up-votes. (Hotfixes normally fix regressions, or core scenarios that block lots of people.) You'd have to supply a very strong business case.

    I don't see any simple workarounds. The bug is a result of miscommunication between ADO and WPF, which you can't affect from the app. The best I can suggest is to try implementing a "wrapper" data model using types that raise the kind of events WPF needs to hear - ObservableCollection<T>, items exposing INotifyPropertyChanged, etc. This is a huge amount of work, as you'll have to translate between ADO's model and the wrapper model, solving the very same communication problems that led to the bug (with no guarantee you can do so). I don't imagine you'd have the time or resources to do it.

    Alternatively, perhaps you could restructure your data to avoid using the "data relations" features of ADO. Again, I don't imagine that's a real option.

    We apologize for the inconvenience caused by this bug, and thank you for reporting it so that we can fix it in the future. I know that doesn't help you today, but given our backlog, priorities, and schedule, it's the best we can do.

    Ma demande au support :

    A simple workaround could be a relinkage among the DataGrid objects, CollectionViewSource objects, and DataViews of the DataTable objects after the commit phase, by reestablishing the binding between them.
    This is the solution I'm trying to pace in the code behind, except that I can not figure out how to get it right in code.
    Unfortunately, I do not have enough knowledge of WPF API to write it by my own.
    This is why I kindly ask for your support. Could you at least bring your technical assistance in carrying it out?

    I feel that you have absolutely no awareness of the importance of this bug and its impact on the framework implementing ADO.NET coupled with WPF.
    For developers coming from the WinForms platform, willing to migrate their applications to WPF, this feature is most crucial for a smooth transition.
    Without a bug fix, the entire binding interface API between ADO.NET and WPF would no longer have any interest. You can throw it into the trash can.
    I suggest you think carefully on it and measure the decisions you will make.
    It's not because this bug was only raised by two people in the entire universe that it takes away any credibility to the thing.
    What is the most valuable foundation of developers today? WinForms or WPF? What is Microsoft's intention for WPF? Is it not WinForms base smooth migration to WPF?
    Otherwise, it would has meant that I did not catch a thing of the whole story.
    If it is so, then forget about it!
    Sincerely

    Raymond

    • Modifié rbmoman samedi 15 juillet 2017 06:16
    vendredi 14 juillet 2017 19:57