This is exactly the same situation that would occur if you generated your business classes against a particular database table, and then someone – a customer, let’s say – subsequently added new columns to that table. The generated business class simply would know nothing about the new columns.
How DevForce Retrieves Data for Your Business Objects
On the “Class” sub-tab of the “Class Detail” tab in the Object Mapper, you will find a dropdown list labeled “Column Selection Options”. The default setting for this property is “SelectAllColumns”; an alternate setting is “AllowColumnSelection”.

Under the default setting, when data is retrieved for one of your business objects, what is retrieved is the entire data row behind that object – including columns for which no properties are defined in the business class. In SQL terms, the retrieval is implemented as a “SELECT *” rather than a “SELECT ColumnName1, ColumnName2, ColumnName3, etc.”. That means, for our customer-added columns scenario, that you get the data for the custom-added columns, even if your business class doesn’t know what to do with it.
To make use of the additional data, you must somehow discover which columns have been retrieved for which no property is defined in the business class. If you can do that, you have the first half of your custom columns problem solved.
Getting a List of Properties Defined in the Business Class
To isolate the custom columns, you need two things:
- a list of the properties currently defined for the business object; and
- a comprehensive list of the columns retrieved.
The custom columns can be isolated by identifying items in the second list that aren’t in the first.
You can get the list of currently defined properties by calling the Get() method of the IdeaBlade.Util.PropertyDescriptorsList class, letting it know the type about which you want information.
C#:
PropertyDescriptorList pdlist = PropertyDescriptorList.Get(typeof(Employee));
VB.NET:
Dim pdlist As PropertyDescriptorList = PropertyDescriptorList.Get(GetType(Employee))
Getting a List of Columns in the Base Table
To get a comprehensive list of the columns defined in the datasource, do the following:
C#:
PersistenceManager.DefaultManager.InitializeSchema(typeof(Employee));
EntityTable employeeTable =
PersistenceManager.DefaultManager.GetTable(typeof(Employee));
foreach(DataColumn col in employeeTable.Columns) {...}
VB.NET:
PersistenceManager.DefaultManager.InitializeSchema(GetType(Employee))
Dim employeeTable As EntityTable =
PersistenceManager.DefaultManager.GetTable(GetType(Employee))
For Each col As DataColumn In employeeTable.Columns
The call to InitializeSchema() tells the PersistenceManager to retrieve the schema for the table on which the business object is based from the datasource. In the normal operation of an app, this schema initialization occurs as a byproduct of other operations, such as a GetEntities() call, or creation of an object of the specified type. In most cases the end result is always the same. However, there is at least one scenario in which the schema created in the PersistenceManager’s cache does not reflect the custom columns. If Create() is called on the business class while the client app is disconnected from the datasource, and before a connected data retrieval has taken place, and before the cache has been restored from a locally stored entity set, the Create() method is forced – having no where else to turn – to look to the business class for its schema information. In doing so, it of course discovers only those properties that were defined in code for the class. Furthermore, the schema, once initialized, remains unchanged until its PersistenceManager is either destroyed or reset with a Clear() call. It never learns about the custom columns.
You can see the rest of the steps required to discover the full column set from the code sample shown above: you call GetTable() on the PersistenceManager to get an EntityTable and then simply iterate through its Columns collection to discover what’s there.
Isolating the Custom Columns
Once you have your two lists, isolating the custom columns is easy: just check, for each column discovered in the schema, for a PropertyDescriptor with a PropertyPath the same as the column name. If it isn’t found, you’ve got a custom column.
C#:
foreach(DataColumn col in employeeTable.Columns) {
PropertyDescriptor pd = pdlist.Find(col.ColumnName);
if (pd == null) {
// Customer-added column found!
CreateAndConfigureOneUiControl(col);
}
}
VB.NET:
For Each col As DataColumn In employeeTable.Columns
Dim pd As PropertyDescriptor = pdlist.Find(col.ColumnName)
If pd Is Nothing Then
' Customer-added column found!
CreateAndConfigureOneUiControl(col)
End If
Next col
Note that the string returned by EntityTable.Columns(n).ColumnName will reflect any renaming done by you in the ObjectMapper. For example, if you rename the property generated from a BirthDate column to “DateOfBirth”, EntityTable.Columns(n).ColumnName will return “DateOfBirth” rather than “BirthDate”. So you needn’t worry that your own renamed properties will be mistaken for custom columns!
That completes your work of discovery to find the columns your customer added to the table after you shipped him your code. In next week’s Tech Tip, you’ll see how to write code that will, at runtime, create temporary properties on your business object for the data from those custom columns. Then, dynamically, you’ll toss some appropriate controls on a form for them and set up data bindings so their values can be displayed and maintained by your customer’s end users. You set all of this up without knowing the first detail about your customer’s post-delivery additions to your tables!