Save data using DataDictionaries
Saving data in an application is one of the things that sets DataFlex appart from many other development environments. Since you define tables and relationships DataFlex knows how to validate save and update data. This saves you alot of time as a developer since you basically only have to pick what fields you want on the screen. Though, the downside is that it is so rarely you actually need to save data, you forget how to do it properly and at least I have to spend more time then I would like to figure out how to do it.
The task for today is to create a new record in a table and save some default information. I do remember that I should use Set Field_Changed_Value of oMy_DD (RefTable(my_table.my_column)) to sValue in order to feed the information to save. I also remember that I should use Send Request_Save of oMy_DD when saving and that there is some code that is good to add around the save to validate. But from time to time I forget this. In this case I also want to clear the oMy_DD in order to add a new record instead of editing the existing one. This puts my forhead in wrinkles since I remeber something about Move 0 to my_table.RECNUM or Set_Attribute DF_FILE_STATUS of my_table.File_Number to DF_FILE_INACTIVE but that is for the Record buffer, not DataDictionaries and it was only when I have data in the buffer and want the save to create a new record , instead of saving it on the same one. In DataDictionaries it is not possible as far as I have heard to do the same stunt. Instead you need to clear the DataDictionary and paste the content in there. But this make me realize that I'm over complicating things. I just need to Send Clear of oMy_DD in order to enter a new record . So, let's start there and get back to copying later.
Before we begin, for you who are new to DataFlex, the two ways of manipulating data in DataFlex, through the Record Buffer and through DataDictionaries could be compared to saving data directly to a table or having a smart object that ensure that all you business rules are maintained. So, ofcourse you want to use DataDictionaries as often as possible. Though if you want to modify the database from code within a DataDictionary Object you need to access the Record Buffer directly since DataDictionaries cannot operate on them selves. That is why I will show both ways in these samples.
Adding a record using the Record Buffer
Clear my_table
Move "Some text" to my_table.my_column
SaveRecord my_table
There is both a Save and a SaveRecord, where the difference is that the Save also update any related parent tables and SaveRecord only saves the selected table.
Using DataDictionaries the same code would look like this.
Boolean bErr
Send Clear of oMy_DD
Set Field_Changed_Value of oMy_DD (RefTable(my_table.my_column)) to sValue
Get Request_Validate of oMy_DD to bErr
If Not bErr Begin
Send Request_Save of oMy_DD
Move (Err) to bErr
End
You might run in to places that starts with Send Request_Clear, this is obsolete and Send Clear is the new standard. We also have a Request_Validate that is used to check all relationsips and the data based on your business rules befor saving. This one line is a really nice bonus of using DataDictionaries.
Now we would like to copy the data from one record to another. Many older DataFlex systems use the DataFlex database. A file based database built on record orientend processing. This included a special column called RECNUM. As more and more system migrate to an SQL-based database the use of RECNUM is actually discuraged. But using the old way. Copying data was as easy as setting the RECNUM to zero like this.
Move 0 to my_table.RECNUM
SaveRecord my_table
Today you need to tell the record buffer that it is inactive. This will prompt the SaveRecord to create a new table without changing any of the data in the other columns of that record.
Set_Attribute DF_FILE_STATUS of my_table.File_Number to DF_FILE_INACTIVE
SaveRecord my_table
There is also a NewRecord that can be used that is a bit cleaner.
NewRecord my_table
SaveRecord my_table
Trying to do this using DataDictionaries on the other hand is not as straight forward. Because when you call Request_Validate or Request_Save the record is activated again inside the DataDictionary. So, it will just update the same record . If you know of a way to change the state of a DataDictionary to create a new record, please tell me and I'll update this post. As far as I understand, the closest way to copy data using DataDictionaries is to first create a dummy object. Then clearing the DataDictionary and after that moving the data in to it.
Boolean bErr Integer iStatus iFieldCount iFieldNr Handle hoDD Get Create (RefClass(cMyDataDictionary)) to hoDD Set Main_File of hoDD to my_table.File_Number Move (Field_Current_Value(oMy_DD , (RefTable(my_table.id)))) to my_table.id Send Request_Find of hoDD EQ my_table.File_Number 1 Send Clear of oMy_DD // Set Field_Changed_Value of oMy_DD (RefTable(my_table.value)) to (Field_Current_Value(hoDD , (RefTable(my_table.value)))) //... repeat for each column you want to copy in your table. Automated solution below Get_Attribute DF_FILE_NUMBER_FIELDS of (RefTable(my_table)) to iFieldCount For iFieldNr from 1 to (iFieldCount) Set Field_Changed_Value of oMy_DD iFieldNr to (Field_Current_Value(hoDD , iFieldNr)) Loop // Then you can modify single columns if you like Set Field_Changed_Value of oMy_DD (RefTable(my_table.value)) to "New data"
Get Request_Validate of oMy_DD to bErr If Not bErr Begin Send Request_Save of oMy_DD Move (Err) to bErr End
As you can see, this is still a quite compact solution. But I'd still prefere a New_Record feature for DataDictionaries.
If you want to learn more about DataDictionaries I have a video series called Working with DataDictionaries where I dive deeper into their different features.
- DataFlex CRUD DataDictionary