I want to display lists of business layer objects in 'grid' controls. I also want to edit any given object in a dialog box.
The objects are persisted in a relational database that also performs referential and multi-user integrity. Although the business objects are quite similar to the database tables, I would like to decouple them to a degree using some sort of 'data mapper'.
My objects are derived from a myDataObject base class. The base class has a static member as follows:
// Initialise a static list of member names for this class. Used when the object is displayed in a grid.
const std::vector<myDataObjectDescriptor> myDataObject::m_Descriptors
{
{ myDO_INT_FIELD, "UID", "m_UID", 40, false, false },
{ myDO_STRING_FIELD, "TITLE", "m_Title", 200, true, false },
{ myDO_STRING_FIELD, "DESCRIPTION", "m_Description", 400, true, false }
};
This descriptor list allows the grid control to directly render the object list with the correct column titles and widths. I can extend the base class descriptors using a lambda:
// Static initialisation of descriptor list using a lamda.
const std::vector<myDataObjectDescriptor> myDerivedDataObject::m_Descriptors = []
{
std::vector<myDataObjectDescriptor> v = myDataObject::m_Descriptors;
v.push_back ({myDO_STRING_FIELD, "BACKGROUND", "m_Background", 120, false, false});
v.push_back ({myDO_STRING_FIELD, "FONT", "m_Font", 120, false, false});
return v;
} ();
So far so good. Now, I would like to create a list of objects from a database query, the list can be a std::vector<some class derived from myDataObject>
. My database layer returns a result set which allows rows to be retrieved one at a time.
How can I write a data mapper that takes a reference to the object list (std:vector<some class derived from myDataObject>&
) and a reference to the result set and populates the list?
Additional info:
Currently I have 2 methods that are overridden in each class derived from myDataObject:
- FromData (myResultSet& resultset): populates 'this' object from the current row in the result set.
- SetByName (string name, variant value): sets an attribute based on its stringified name. Used by FromData to set an attribute based on the field name in the result set.
There are multiple things that I don't like about this, but mostly:
- myDataObject shouldn't know anything about the database layer (too closely coupled).
SetByName is a series of if statements that sets an attribute if the 'name' parameter is matched, i.e.
if (name == "m_Title") m_Title = value;
Edit re. comment by rumburak: Once I have solved the problem of reading, it is my plan to somehow do the reverse for persisting data.