Using MD5 as standardized way to test if a record is changed

I have made a simple Method to loop through all fields on a DataForm to test if any of the fields is changed by the user. I store a variable of the MD5text as I load the DataRecord and then compares when user closes the form, if I need to Save the record. But I need to test for each ControlType to get the ‘Value’.

Are there any more brilliant ideas, out there? and what if data is Stored in a DataRecord Class, how to optimize the test if any data have been changed? Or Am I way off in my thinking here?

Method CalcFormMD5
Var c As Control
Var MD5text As Text

Try
For i As Integer = 0 To Self.ControlCount - 1
c = Self.Control(i)

Select Case c
Case IsA TextField
  MD5text = MD5text + TextField(c).Value.ToText

Case IsA TextArea
  MD5text = MD5text + TextArea(c).Value.ToText
  
Case IsA CheckBox
  MD5text = MD5text + Str(CheckBox(c).Value).ToText
  
Case IsA RadioButton
  MD5text = MD5text + Str(RadioButton(c).Value).ToText
  
Case IsA PopupMenu
  MD5text = MD5text + PopupMenu(c).SelectedRowValue.ToText
  
Case IsA ComboBox
  MD5text = MD5text + ComboBox(c).SelectedRowValue.ToText
  
Case IsA Slider
  MD5text = MD5text + Slider(c).Value.ToText
  
End Select

Next

End Try
Return MD5(Str(MD5text).DefineEncoding(Encodings.UTF8))

I don’t see anything majorly wrong with your solution. Some feedback on your code:
• It looks like you are constantly switching between String & Text. Personally, I would just use String.
• You might need to filter out certain controls that are on the form but shouldn’t be stored.

Storing your data as properties in a class might help in other areas but I cannot see any massive benefit in doing so to simply compare old & new values.

You need some sort of unique separator between the values to make sure values don’t bleed into each other. Your current implementation would detect TextField1.Value = "AB" + TextField2.Value = "CD" the same as TextField1.Value = "ABC" + TextField2.Value = "D". Another problem is your solution relies on the order the controls are listed by Window.Control. It might be worth including the control names and sorting. For example

Var Bound As Integer = Self.ControlCount - 1 Var Pieces() As String For Idx As Integer = 0 To Bound Try Dim Target As RectControl = Self.Control(Idx) Select Case Target Case IsA TextField Pieces.AddRow(Target.Name + ":" + TextField(Target).Value) End Select Catch Err As RuntimeException End Try Next Pieces.Sort Return EncodeHex(Crypto.MD5(String.FromArray(Pieces, "3a81305c-a88d-43ad-8364-4e438854e6e4")))

Of course I left off the full Select statement, and this is written in a browser, but the idea should be correct.

you could subclass your ui elements and memory the value so you can compare it later.

if TextField.Modified or CheckBox.Modified PopupMenu.Modified then
write to database
end if

or just write your data into database with a timestamp.
you could check the timestamp before writing to check if someone else edit this at the “same” time.

Thom, i assume i call the method above when reading the record in the beginning and then when about to write the record at the end… and then check the 2 MD5 value??

Well personally it’s not my favorite way to do things, but yes that’s the general idea. What I don’t like about this approach is the field data being WYSIWYG. As in a slider might be used for a percentage, so 0-100, but in a database I’d store that as a decimal. I’d work towards comparing values field-by-field and issuing an update statement for only the values that have actually changed. Definitely more work and harder to generalize though, but it’s been my experience that these “whole record” comparisons never work out as the project complexity increases.

what i did before is to reread the record just before saving and compare with the textarea, combobox etc and there changes, change the indicator and save the record. if there isn’t any changes, then don’t save.

then recently, the second method is to read into array when reading record and then compare the array with the control just before saving.

Personally, I would take @Thom McGrath suggestions, and not bother using MD5. You can tell if the data is different from just a string comparison, and save the time that it takes to MD5 the data.

Alternatively, add a boolean to your editing window, when any of the controls are changed, flip that boolean to true. You need to make sure that you set it to false as soon as you’ve finished displaying the data or you’ll get false positives.

If you use an Undo system, you can record the number of entries on window open and then compare it with the number of entries to see what’s changed.

You don’t even have to add a Boolean! Window has a ContentsChanged property (API 1) that even does the close dot indicator on Mac!