1. #1
    Membre éclairé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    février 2004
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : février 2004
    Messages : 703
    Points : 842
    Points
    842

    Par défaut ForeignKeyConstraint leve une exception suite à suppression de la ligne parente

    Bonjour,
    Dans une relation maître/Détail entre 2 DataTable la propriété DeleteRule est initialisée à Rule.none.
    Lorsque l'utilisateur supprime la ligne parente, une exception est générée.
    Comment puis-je faire pour que l'exception ne soit pas propagée ?
    Je souhaiterais plutôt afficher une alerte indiquant que la suppression est impossible car des lignes enfants existent dans la table détaille.
    Merci de votre aide
    .
    Pour la défense de nos droits, merci de voter pour : https://connect.microsoft.com/Visual...wupdated-event
    together we stand, divided we fall
    .

  2. #2
    Membre expert Avatar de jopopmk
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mars 2011
    Messages
    1 829
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mars 2011
    Messages : 1 829
    Points : 3 426
    Points
    3 426

    Par défaut

    Salut,

    Si tu veux interdire la suppression en cas d'erreur FK ne suffirait-il pas de catcher cette exception spécifiquement et d'afficher une MessageBox le cas échéant ? Sinon au cas où : pour une suppression en cascade il doit y avoir une Rule genre deleteCascade. Autre solution : les orphelins, que je déconseille.
    Plus je connais de langages, plus j'aime le C.

  3. #3
    Membre éclairé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    février 2004
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : février 2004
    Messages : 703
    Points : 842
    Points
    842

    Par défaut

    Càd que l'exception se propage jusqu'à la méthode Main de l'application, et hormis le gérer à ce niveau dans un try catch, je ne vois pas où le faire autrement.
    Je ne trouve pas cela très élégant...
    Y aurait-il une autre solution à cela comme un évènement dans lequel je pourrais gérer l'exception ?
    Merci encore de votre concours
    .
    Pour la défense de nos droits, merci de voter pour : https://connect.microsoft.com/Visual...wupdated-event
    together we stand, divided we fall
    .

  4. #4
    Membre expert Avatar de jopopmk
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mars 2011
    Messages
    1 829
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mars 2011
    Messages : 1 829
    Points : 3 426
    Points
    3 426

    Par défaut

    Ben c'est le fonctionnement normal de la programmation par exception, après ça dépend de ton archi. La fonction qui fait l'appel qui lève l'exception pourrait la catcher en interne et renvoyer un code erreur, qui lui sera alors gérer dans une couche supérieure (a priori faut remonter à la vue si tu veux générer une MessageBox).
    Plus je connais de langages, plus j'aime le C.

  5. #5
    Membre éclairé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    février 2004
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : février 2004
    Messages : 703
    Points : 842
    Points
    842

    Par défaut

    Le mieux serait que je vous présente le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
                    // Relie les tables Clients et Commandes
                    datarelationClientCommandes = new DataRelation("datarelationClientCommandes",
                        datatableClients.Columns["Client_ID"], datatableCommandes.Columns["Client_ID"], true); // Par defaut true cree les contraintes
                    datasetLocalDataBase.Relations.Add(datarelationClientCommandes);
                    ForeignKeyConstraint foreignkeyClientCommandes = datasetLocalDataBase.Relations["datarelationClientCommandes"].ChildKeyConstraint;
                    foreignkeyClientCommandes.DeleteRule = Rule.None;
                    foreignkeyClientCommandes.UpdateRule = Rule.None;
                    foreignkeyClientCommandes.AcceptRejectRule = AcceptRejectRule.None;
    J'instancie la relation entre les 2 tables dans la méthode Load d'une Windows Form.
    L'utilisateur supprime une ligne dans le DataGridView de la table maître Clients qui possède des lignes enfants dans la table détaille Commandes
    L'application lève l'exception InvalidConstraintException dans la méthode Main() sur la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application.Run(new DBGrid());
    Le trace de l'exception est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    'DBGrid.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Data.resources\2.0.0.0_fr_b77a5c561934e089\System.Data.resources.dll'
    A first chance exception of type 'System.Data.InvalidConstraintException' occurred in System.Data.dll
    'DBGrid.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Transactions.resources\2.0.0.0_fr_b77a5c561934e089\System.Transactions.resources.dll'
    System.Transactions Critical: 0 : <TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Critical"><TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier><Description>Exception non gérée</Description><AppDomain>DBGrid.vshost.exe</AppDomain><Exception><ExceptionType>System.Data.InvalidConstraintException, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Impossible de supprimer cette ligne, car les contraintes sont appliquées sur la relation datarelationClientCommandes. La suppression de cette ligne rendra les lignes enfants orphelines.</Message><StackTrace>   à System.Data.ForeignKeyConstraint.CascadeDelete(DataRow row)
       à System.Data.ForeignKeyConstraint.CheckCascade(DataRow row, DataRowAction action)
       à System.Data.DataTable.CascadeAll(DataRow row, DataRowAction action)
       à System.Data.DataTable.RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, Boolean fireEvent)
       à System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Int32 position, Boolean fireEvent, Exception&amp;amp; deferredException)
       à System.Data.DataTable.SetNewRecord(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean fireEvent)
       à System.Data.DataTable.DeleteRow(DataRow row)
       à System.Data.DataRow.Delete()
       à System.Data.DataView.Delete(DataRow row)
       à System.Data.DataView.System.Collections.IList.RemoveAt(Int32 index)
       à System.Windows.Forms.BindingSource.RemoveAt(Int32 index)
       à System.Windows.Forms.BindingSource.RemoveCurrent()
       à System.Windows.Forms.BindingNavigator.OnDelete(Object sender, EventArgs e)
       à System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
       à System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
       à System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
       à System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
       à System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
       à System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
       à System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
       à System.Windows.Forms.Control.WmMouseUp(Message&amp;amp; m, MouseButtons button, Int32 clicks)
       à System.Windows.Forms.Control.WndProc(Message&amp;amp; m)
       à System.Windows.Forms.ScrollableControl.WndProc(Message&amp;amp; m)
       à System.Windows.Forms.ToolStrip.WndProc(Message&amp;amp; m)
       à System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&amp;amp; m)
       à System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&amp;amp; m)
       à System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       à System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG&amp;amp; msg)
       à System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       à System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       à System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       à System.Windows.Forms.Application.Run(Form mainForm)
       à DBGrid.Program.Main() dans C:\Users\raymond\Documents\CSharpBase\DBGrid\DBGrid\Program.cs:ligne 18
       à System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       à System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       à Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       à System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       à System.Threading.ThreadHelper.ThreadStart()</StackTrace><ExceptionString>System.Data.InvalidConstraintException: Impossible de supprimer cette ligne, car les contraintes sont appliquées sur la relation datarelationClientCommandes. La suppression de cette ligne rendra les lignes enfants orphelines.
       à System.Data.ForeignKeyConstraint.CascadeDelete(DataRow row)
       à System.Data.ForeignKeyConstraint.CheckCascade(DataRow row, DataRowAction action)
       à System.Data.DataTable.CascadeAll(DataRow row, DataRowAction action)
       à System.Data.DataTable.RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, Boolean fireEvent)
       à System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Int32 position, Boolean fireEvent, Exception&amp;amp; deferredException)
       à System.Data.DataTable.SetNewRecord(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean fireEvent)
       à System.Data.DataTable.DeleteRow(DataRow row)
       à System.Data.DataRow.Delete()
       à System.Data.DataView.Delete(DataRow row)
       à System.Data.DataView.System.Collections.IList.RemoveAt(Int32 index)
       à System.Windows.Forms.BindingSource.RemoveAt(Int32 index)
       à System.Windows.Forms.BindingSource.RemoveCurrent()
       à System.Windows.Forms.BindingNavigator.OnDelete(Object sender, EventArgs e)
       à System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
       à System.Windows.Forms.ToolStripButton.OnClick(EventArgs e)
       à System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
       à System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
       à System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
       à System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
       à System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
       à System.Windows.Forms.Control.WmMouseUp(Message&amp;amp; m, MouseButtons button, Int32 clicks)
       à System.Windows.Forms.Control.WndProc(Message&amp;amp; m)
       à System.Windows.Forms.ScrollableControl.WndProc(Message&amp;amp; m)
       à System.Windows.Forms.ToolStrip.WndProc(Message&amp;amp; m)
       à System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&amp;amp; m)
       à System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&amp;amp; m)
       à System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       à System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG&amp;amp; msg)
       à System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       à System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       à System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       à System.Windows.Forms.Application.Run(Form mainForm)
       à DBGrid.Program.Main() dans C:\Users\raymond\Documents\CSharpBase\DBGrid\DBGrid\Program.cs:ligne 18
       à System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       à System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       à Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       à System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       à System.Threading.ThreadHelper.ThreadStart()</ExceptionString></Exception></TraceRecord>
    Mon soucis est que je ne vois pas où je pourrais traiter l'exception hormis dans un bloc try dans la méthode Main().
    Je souhaiterais le gérer plus élégamment si cela est possible.
    Connaitriez-vous la meilleure manière de la programmer ?
    .
    Pour la défense de nos droits, merci de voter pour : https://connect.microsoft.com/Visual...wupdated-event
    together we stand, divided we fall
    .

  6. #6
    Membre éclairé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    février 2004
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : février 2004
    Messages : 703
    Points : 842
    Points
    842

    Par défaut

    Bon ben s'il n'y a pas d'autres solutions, je crois bien que seul un DeleteRule = Rule.Cascade me permettra de me sortir de la situation
    C'est un peu dommage car "cascader" simplement sans se poser de questions, c'est un peu dangereux à mon goût...
    Mais bon, c'est chacun qui voyait midi
    .
    Pour la défense de nos droits, merci de voter pour : https://connect.microsoft.com/Visual...wupdated-event
    together we stand, divided we fall
    .

  7. #7
    Rédacteur/Modérateur

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    juillet 2016
    Messages
    1 456
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juillet 2016
    Messages : 1 456
    Points : 4 869
    Points
    4 869
    Billets dans le blog
    5

    Par défaut

    Bonjour,

    Peut-être une possibilité. DataGridView dispose d'un événement UserDeletingRow qui est appelé avant la suppression de la ligne, suite à une action de la part de l'utilisateur.

    Mon idée ici serait d'ajouter un handler à cet événement, à annuler la suppression, et à gérer ensuite manuellement la suppression directement au niveau de la DataTable que tu peux ainsi mettre dans un bloc try/catch et donc gérer cela plus finement.
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  8. #8
    Membre éclairé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    février 2004
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : février 2004
    Messages : 703
    Points : 842
    Points
    842

    Par défaut

    Merci François
    En effet, je pourrais très bien inhiber la suppression en amont si la ligne parente possède des lignes enfantes, ainsi la contrainte ne sera jamais enfreinte, ou bien capturer l'exception dans le gestionnaire.
    Je me demandais simplement si ADO.Net intégrait à l'instar de l'évènement RowUpdated d'un DataAdapter, un évènement pour éventuellement gérer l'exception avant de la propager le cas échéant. Manifestement, cela n'est pas prévu.
    En tout cas merci pour tes suggestions
    .
    Pour la défense de nos droits, merci de voter pour : https://connect.microsoft.com/Visual...wupdated-event
    together we stand, divided we fall
    .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Probleme de ressource, System.Windows.Markup.StaticExtension leve une exception
    Par Interfector dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 06/11/2014, 17h41
  2. [VS2005] S'arreter quand une exception est levée
    Par ZePostman dans le forum Visual Studio
    Réponses: 8
    Dernier message: 28/08/2008, 16h24
  3. [VBA-E] Incrémentation automatique d'une valeur suite à l'insertion de ligne
    Par abdelghani_k dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 31/01/2007, 15h26
  4. Réponses: 36
    Dernier message: 26/04/2006, 15h44
  5. Expliciter une exception levée par un objet OLE
    Par Bleuarff dans le forum Windows
    Réponses: 3
    Dernier message: 12/05/2005, 17h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo