Problème de mise à jour d'une table

Noor-rayann - Modifié le 22 sept. 2022 à 02:55
Whismeril
Messages postés
17804
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 septembre 2022
- 22 sept. 2022 à 23:30

Bonjour chers membres du forum, j'ai une préoccupation qui est liée à la mise à jour de ma table.

En effet j'ai conçu une application vb.net pour la gestion des opérations de caisse d'une structure et tout fonctionne correctement jusqu'au niveau de la modification de la table où j'ai un bémol.

Le truc c'est qu'une opération est soit une recette ou une dépense d'où j'ai créé une variable solde = recette - dépense (recette ou dépense est nulle selon la nature de l'opération) qui représente le solde de chaque opération effectuée.

Pour ce qui est de la part du solde de la caisse à partir d'une opération op2  on a:

E1: solde_caisse_op2 = solde_op2 - solde_op1 et cela fonctionne bien en insertion. 

Mon problème est que sur par exemple 10 opérations effectuées on décide de modifier la 5ème opération, comment réajuster le solde de la caisse à partir de la ligne modifiée jusqu'au dernier élément de la table solde_caisse, vu que les différentes lignes sont dépendantes pour le calcul des différentes soldes de la caisse d'après l'équation E1.

Je compte sur chacun pour la résolution de cette difficulté. Merci...

9 réponses

Whismeril
Messages postés
17804
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 septembre 2022
616
22 sept. 2022 à 09:29

Bonjour

La première question à se poser est : As-tu vraiment besoin que le solde soit stocké dans la base de données ?

Par ce que le solde, c'est le résultat d'une somme. Donc ça peut n'être géré qu'à l'affichage.

La deuxième question à se poser est : Dans la base de données, est-il nécessaire d'avoir un champ dépense et un champ recette, car dans les 2 cas, c'est un mouvement qui est soit positif, soit négatif.

Et donc pareil, la séparation en 2 colonnes peut très bien n'être gérée qu'à l'affichage.


Quand j'étais petit, la mer Morte n'était que malade.
George Burns

0

whismeril supposons que je fasse à ta manière, c'est à dire ne gérer le solde de la caisse qu'à l'affichage, comment pourrais-je m'en prendre en sql?

0
Whismeril
Messages postés
17804
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 septembre 2022
616
22 sept. 2022 à 12:32

En sql je ne sais pas, mais avec Linq je sais.


Quand j'étais petit, la mer Morte n'était que malade.
George Burns

0

ok propose moi donc ta démarche avec Linq

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Whismeril
Messages postés
17804
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 septembre 2022
616
Modifié le 22 sept. 2022 à 12:50

Tu écris une classe métiers dont tous les champs de ta base sont transcrits en propriétés en lecture et écriture.

Tu ajoutes 2 propriétés en lecture et écriture

  • Recette
  • Dépense

Et une propriété en lecture seule

  • Solde

Recette affiche 0 ou null, si mouvement est négatif et la valeur du mouvement s'il est positif

Dépense affiche l'inverse.

Quand elles sont éditées, ces propriétés mettent à jour la propriété mouvement.


Quand mouvement est modifié (ta classe pourrait implémenter INotifyPropertyChanged {d'ailleurs si tu utilises le binding c'est déjà fait} ou alors, tu peux créer un événement spécifique), il faut mettre à jour toutes les instances suivantes.

Un simple For devrait suffire. Mais on peut faire une requette linq.


En y réfléchissant, si tu fais en sorte que tes instances soient chainées, y'a p'tet même pas besoin de For.


Quand j'étais petit, la mer Morte n'était que malade.
George Burns

0

Linq est tout nouveau pour moi, je me penche sur le for. comment je fais donc?

0
Whismeril
Messages postés
17804
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 septembre 2022
616
22 sept. 2022 à 13:17

Je peux te faire un exemple sur la base d'un csv soit en winform, soit en WPF, à toi de me dire


Quand j'étais petit, la mer Morte n'était que malade.
George Burns

0
Whismeril
Messages postés
17804
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 septembre 2022
616
Modifié le 22 sept. 2022 à 15:51

Bon, sans réponse de ta part et ayant un peu de temps là, mais plus après, voilà un exemple en winform

D'abord le fichier CSV

2022/01/01 12:00:00;Ouverture du compte;1000
2022/01/01 14:00:00;Courses;-150
2022/01/02 8:00:00;Carburant;-100
2022/01/03 13:00:00;Etrennes;200

Ensuite la classe métier

Imports System.ComponentModel

Namespace WindowsFormsApp1
    Friend Class Transaction
        Implements INotifyPropertyChanged
        Private datationField As Date
        ''' <summary>
        ''' Date et heure de la transaction
        ''' </summary>
        Public Property Datation As Date
            Get
                Return datationField
            End Get
            Set(ByVal value As Date)
                If datationField = value Then Return
                datationField = value

                'On signale le changement de la datation
                GenerePropertyChanged("Datation")
            End Set
        End Property


        Private libelleField As String
        ''' <summary>
        ''' Libellé de la transaction
        ''' </summary>
        Public Property Libelle As String
            Get
                Return libelleField
            End Get
            Set(ByVal value As String)
                If Equals(libelleField, value) Then Return
                libelleField = value

                'on signale le changement du libellé
                GenerePropertyChanged("Libelle")
            End Set
        End Property


        Private mouvementField As Double
        ''' <summary>
        ''' Mouvement de la transaction
        ''' </summary>
        Public Property Mouvement As Double
            Get
                Return mouvementField
            End Get
            Set(ByVal value As Double)
                If mouvementField = value Then Return
                mouvementField = value

                'On signale le changement du mouvement de tout ce qui en dépend
                GenerePropertyChanged("Mouvement", "Recette", "Depense", "Solde")
            End Set
        End Property

        ''' <summary>
        ''' Recette si c'est le cas
        ''' </summary>
        Public Property Recette As Double
            Get
                Return If(Mouvement > 0, Mouvement, 0)
            End Get
            Set(ByVal value As Double)
                Mouvement = value
            End Set
        End Property

        ''' <summary>
        ''' Dépense si c'est le cas
        ''' </summary>
        Public Property Depense As Double
            Get
                Return If(Mouvement < 0, -1 * Mouvement, 0)
            End Get
            Set(ByVal value As Double)
                Mouvement = -1 * value
            End Set
        End Property


        Private soldePrecedent As Double = 0
        ''' <summary>
        ''' Solde => Solde précédent + mouvement de cette instance
        ''' </summary>
        Public ReadOnly Property Solde As Double
            Get
                Return soldePrecedent + mouvementField
            End Get
        End Property

        ''' <summary>
        ''' Met à jour le solde précédent quand il a changé
        ''' </summary>
        ''' <param name="LeSoldePrecedent"></param>
        Public Sub MajSoldePrecedent(ByVal LeSoldePrecedent As Double)
            soldePrecedent = LeSoldePrecedent
            GenerePropertyChanged("Solde")
        End Sub

        ''' <summary>
        ''' Méthode abonnée aux changements de la transaction précédente
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        Private Sub Precedente_PropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
            If Equals(e.PropertyName, "Solde") Then GenerePropertyChanged("Solde") ' si le solde précédent a changé, on signale que celui-ci change aussi
        End Sub

        ''' <summary>
        ''' Méthode permettant de signaler la mise à jour de certaines valeurs
        ''' </summary>
        ''' <param name="NomsProprietes"></param>
        Private Sub GenerePropertyChanged(ParamArray NomsProprietes As String())
            For Each nom In NomsProprietes
                RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(nom))

                If nom = "Solde" Then RaiseEvent SoldeChanged(Me)
            Next
        End Sub

        ''' <summary>
        ''' Implémentation de INotifyPropertyChanged, pour la mise à jour du binding
        ''' </summary>
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

        ''' <summary>
        ''' Evènement qui signale que le solde a changé et donc qu'il faut recalculer l'instance suivante
        ''' </summary>
        ''' <param name="sender"></param>
        Public Event SoldeChanged(ByVal sender As Transaction)
    End Class
End Namespace

Et le code dans le formulaire

        Private lesTransactions As BindingList(Of Transaction) 'liste de Transactions à binder

        Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)

            'Lecture du fichier csv pour construire la liste de Transactions
            Dim datasCSV = File.ReadAllLines("exemplegeekmtl.csv")
            lesTransactions = New BindingList(Of Transaction)()
            Dim soldePrecedent As Double = 0

            For Each ligne In datasCSV
                Dim datas = ligne.Split(";"c)
                Dim nouvelle As Transaction = New Transaction With
                {
                    .Datation = Date.Parse(datas(0)),
                    .Libelle = datas(1),
                    .Mouvement = Double.Parse(datas(2))
                }
                nouvelle.MajSoldePrecedent(soldePrecedent)

                lesTransactions.Add(nouvelle)

                AddHandler nouvelle.SoldeChanged, AddressOf Transaction_SoldeChanged ' on s'abonne à l'évènement pour savoir quand mettre à jour l'instance suivante
                soldePrecedent = nouvelle.Solde
            Next

            transactionBindingSource.DataSource = lesTransactions 'binding sur un BindingSource configuré pour ne pas afficher le mouvement

        End Sub

        Private Sub Transaction_SoldeChanged(ByVal sender As Transaction)

            'le solde de l'instance "sender" a changé, il faut mettre à jour la suivante

            Dim indexEncours = lesTransactions.IndexOf(sender)

            If indexEncours < lesTransactions.Count - 1 Then
                'on met à jour le solde de la suivante
                lesTransactions(indexEncours + 1).MajSoldePrecedent(sender.Solde)
                'ça va déclencher l'évènement de cette instance et donc revenir ici pour faire faire la mise à jour de la suivante, etc. …
            End If

        End Sub

Au démarrage

Après avoir mis à jour une recette (idem pour une dépense)

Je n'ai pas géré l'ajout (ou l'insertion) ni la suppression d'une transaction, mais dans un cas comme dans l'autre, il faudra déclencher une mise à jour du solde de la suivante.


Quand j'étais petit, la mer Morte n'était que malade.
George Burns

0
vb95
Messages postés
3056
Date d'inscription
samedi 11 janvier 2014
Statut
Modérateur
Dernière intervention
22 septembre 2022
158
22 sept. 2022 à 18:52

Ce code là c'est du grand Whismeril !

0
Whismeril
Messages postés
17804
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
25 septembre 2022
616 > vb95
Messages postés
3056
Date d'inscription
samedi 11 janvier 2014
Statut
Modérateur
Dernière intervention
22 septembre 2022

22 sept. 2022 à 23:30

:)

0

ok je vais suivre ta démarche et voir ce que ça va donner, merci déjà pour ta disponibilité et je te reviens... 

0