Introduction
Data Transfer Object (DTO) is an entity used for distributing data across layers. DTO should be a serializable class with related properties defined and in runtime it will be filled with business competitive values for transfer and further processing. DataTableSpecial – particularly addresses the area where varied data results coming from data source used for viewing and editing purposes. The article initiates thinking on using DataTable as Generic DTO.
Background
Consider the scenario where an application is showing multiple views on sales data for analysis purposes. Let's say, there are ten separate stored procedures for it (and all these are joining few more tables with sales table for detailed analysis views). When a user selects any particular view on the user interface, the corresponding view generation stored procedure executes and returns its own set of data columns. Like that, ten stored procedures return data with ten different set of data columns and we want to design a generic data transfer object to make programming easy. We may end up investing more time on creating something complicated.
There are a couple of approaches which quickly come to our mind, creating a separate DTO object for each view or creating an object which has all properties from ten views or using a dataset. Each one has its own merits and demerits.
Using DataTable
In .NET 2.0, DataTable has been improved a lot in terms of functionality and performance. It is serializable, light weight, dynamically gets structured when varied results are emitted by stored procedure and we can use DataReader for filling this object which is faster-read only-forward operation. In multiple data view screen, say, I am using gridview. Since it's a DataTable, I can easily bind it to a grid.
Challenge with DataTable
In some scenarios, the user wishes to edit a particular row data and our application layers familiar only with custom business or typed objects for processing. If we are using DataTable, each row is of DataRow type and we want this to be molded into our custom business object so that our business layer can consume it properly. We may start writing ten molding methods (for ten views). DataTableSpecial solves this problem.
What Does DataTableSpecial Do?
Configuration driven and extendible DataTableSpecial component offers flexibility of emitting a custom business object on the fly. For a particular row, if I want to emit a custom business object which is already created in my application, I expect to write simple code like this:
Item i = (Item) dataTableSpecial.CreateCustomObject(<Row_Number>,
"<business object name>",
"<object properties and DB column mapping tag name>");
For example:
Item i = (Item) dataTableSpecial.CreateCustomObject(2, "Item",
"ItemDetails");
During custom object creation, DataTableSpecial actually refers to the MapConfig.xml file (placed with running assembly). Let's check what MapConfig.xml has.
<DataTableSpecialConfig>
<CustomObject name="Item" QualifiedObjectName="DataTableSpecial.Item"
AssemblyFile="DataTableSpecialDemo.exe" >
<ObjectMapping name="ItemDetails">
<map ColumnName="ITM_KEY" PropertyName="ID" />
:
</ObjectMapping>
</CustomObject>
</DataTableSpecialConfig>
Attribute name in CustomObject node can be a user defined name. This name will be referred in code as the second argument of CreateCustomObject() method to indicate which object should be created for a selected row. QualifiedObjectName should be Namespace.ClassName.
Attribute name in ObjectMapping node can be a user defined name. This name will be referred in code as the third argument of CreateCustomObject() method. Mapping defined under this node should be proper because this is the important portion for DataTableSpecial component to dump data from the data row to a specified custom business object.
If you are using different objects to dump data row details, then you can define multiple CustomObject nodes with a unique name.
If you are fetching different data columns in a single object type depending on view requirements, then create multiple ObjectMapping nodes with unique name under the CustomObject root node.
Using the Code
CreateCustomObject is an extended method in DataTableSpecial component and the rest are all inherited from the .NET DataTable.
IDataReader dr = GetData();
DataTableSpecial dt = new DataTableSpecial("PURCHASES");
dt.Load(dr);
dataGridView1.DataSource = dt;
Item i = (Item) dt.CreateCustomObject(2, "Item", "ItemDetails");
MessageBox.Show(i.ToString());
Please note that I have removed all validation and error checking code to make the demo clear and simple to understand. You are free to update the source as per your requirement.
Final Points
- A quick solution for those who are not using any proprietary ORM tools
- Interchangeable with
DataTable since DataTableSpecial is an inherited version
- Flexible, less memory consuming and bindable
- Configuration driven, simple and easy to understand for further improvements