Hallo zusammen.
Ich hab mir nen kleinen "DataLogger" gebaut. Hiermit betreibe ich eine Änderungsverfolgung in meinem Programm. Man kann also nachschauen, wer hat wann was an einem Datensatz gemacht.
Spoiler anzeigen
Ein Beispielaufruf (beim Editieren) - in Zeile 8 wird der Logger initialisiert, in Zeile 9 (also nach dem Edit) wird mit alten Werten verglichen und ggf. angepasst:
Spoiler anzeigen
Das funktioniert wunderbar für bereits vorhandene Datensätze, allerdings nicht für Neue.
Das Problem ist, dass ich VOR der Neuanlage die neue DataRow nicht kenne - und danach weiß man nicht wirklich, welche die gerade erstellte ist...
Die folgenden beiden Methoden nutze ich zur Neuanlage von Datensätzen (dahinter stecken Extensions von @ErfinderDesRades):
Spoiler anzeigen
Ich müsste hier nach Zeile 6 bzw. nach Zeile 19 die gerade erstellte DataRow abfangen. Kann mir jemand sagen, wie ich das geschickt anstelle?
Hat die Bindingsource eine Eigenschaft, den zuletzt erstellen Datensatz zu finden?
Ich hab mir nen kleinen "DataLogger" gebaut. Hiermit betreibe ich eine Änderungsverfolgung in meinem Programm. Man kann also nachschauen, wer hat wann was an einem Datensatz gemacht.
VB.NET-Quellcode
- Public Class DataLogger
- 'TODO: auch neue Datensätze loggen mit "Erstanlage", dafür muss aber nach dem Speichern irgendwie die korrekte ID rausgefunden werden...
- Private Shared _BearbeitungsTyp As String
- Private Shared _OldValues As Dictionary(Of DataRow, Object())
- Private Shared _RwNew As DataLogRow
- Public Sub New(Typ As String, ParamArray Drs As DataRow())
- _BearbeitungsTyp = Typ
- _OldValues = New Dictionary(Of DataRow, Object())
- Drs.ForEach(Sub(dr) _OldValues.Add(dr, dr.ItemArray))
- End Sub
- ''' <summary>Änderungsverfolgung: Vergleicht die Werte aller DataRows in _OldValues mit ggf. geänderten Werten. Gibt es Änderungen, werden diese in der Tabelle
- ''' DataLog mit zusätzlichen Informationen abgespeichert</summary>
- Friend Sub CompareValuesAndStoreChanges()
- Dim DicNegativeRecordID As New Dictionary(Of DataLogRow, DataRow)
- For Each kvp In _OldValues
- Dim dr = kvp.Key
- Dim oldValues = kvp.Value
- Dim columns = dr.Table.Columns
- Dim recordID = If(dr.Table.Columns(0).ColumnName = "ID", CInt(dr.Item(0).ToString), 0)
- For iCol = 0 To columns.Count - 1
- Dbg($"DataLogger: {dr.Table.TableName} Alter Wert: {oldValues(iCol)}")
- Dbg($"DataLogger: {dr.Table.TableName} Neuer Wert: {dr.Item(iCol)}")
- If dr.Item(iCol).ToString <> oldValues(iCol).ToString Then
- _RwNew = Dts.DataLog.AddDataLogRow(dr.Table.TableName, User.UserName, Date.Now, recordID, columns(iCol).ColumnName, oldValues(iCol).ToString, dr.Item(iCol).ToString, _BearbeitungsTyp)
- If recordID < 0 Then DicNegativeRecordID.Add(_RwNew, dr)
- End If
- Next
- Next
- If DicNegativeRecordID.Count > 0 Then
- Dts.SaveDts() 'Speichern ist hier notwendig, damit negative ID's in positive aus der DB umgewandelt werden.
- For Each kvp In DicNegativeRecordID
- kvp.Key.DatensatzID = CInt(kvp.Value.Item(0).ToString)
- Next
- End If
- End Sub
- End Class
Ein Beispielaufruf (beim Editieren) - in Zeile 8 wird der Logger initialisiert, in Zeile 9 (also nach dem Edit) wird mit alten Werten verglichen und ggf. angepasst:
VB.NET-Quellcode
- ''' <summary>Öffnet einen Dialog zum Bearbeiten des gewählten Datensatzes</summary>
- <Extension>
- Friend Sub ShowEditDialog(dgv As DataGridView, editdlg As Form)
- Dim bs = DirectCast(dgv.DataSource, BindingSource)
- Dim dr = DirectCast(bs.Current, DataRowView).Row
- Dim rLock As New RecordLock(bs.DataTable, CInt(dr.Item(0)))
- If Not rLock.LockRecord Then Return
- Dim logger As New DataLogger("Bearbeitet", dr)
- If bs.EditCurrent(editdlg) = DialogResult.OK Then logger.CompareValuesAndStoreChanges()
- rLock.UnlockRecord()
- End Sub
Das funktioniert wunderbar für bereits vorhandene Datensätze, allerdings nicht für Neue.
Das Problem ist, dass ich VOR der Neuanlage die neue DataRow nicht kenne - und danach weiß man nicht wirklich, welche die gerade erstellte ist...
Die folgenden beiden Methoden nutze ich zur Neuanlage von Datensätzen (dahinter stecken Extensions von @ErfinderDesRades):
VB.NET-Quellcode
- ''' <summary>Öffnet einen Dialog zur Neuanlage eines Datensatzes</summary>
- <Extension>
- Public Function ShowCreateNewDialog(dgv As DataGridView, editDlg As Form) As Boolean
- Dim bs = DirectCast(dgv.DataSource, BindingSource)
- Try
- If bs.EditNew(editDlg) = DialogResult.OK Then Return True
- Catch ex As Exception
- msgEx(ex)
- bs.CancelEdit()
- Return False
- End Try
- Return False
- End Function
- ''' <summary>Öffnet einen Dialog zur Neuanlage eines Datensatzes</summary>
- <Extension>
- Public Function ShowCreateNewDialog(Of T As {Form, New})(BS As BindingSource) As Boolean
- Try
- If BS.EditNew(Of T) = DialogResult.OK Then Return True
- Catch Ex As Exception
- msgEx(Ex)
- BS.CancelEdit()
- Return False
- End Try
- Return False
- End Function
Ich müsste hier nach Zeile 6 bzw. nach Zeile 19 die gerade erstellte DataRow abfangen. Kann mir jemand sagen, wie ich das geschickt anstelle?
Hat die Bindingsource eine Eigenschaft, den zuletzt erstellen Datensatz zu finden?
"Na, wie ist das Wetter bei dir?"
"Caps Lock."
"Hä?"
"Shift ohne Ende!"
"Caps Lock."
"Hä?"
"Shift ohne Ende!"

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „tragl“ ()