First, I create an Abstract Class for my DataTables Common Code. This class Inherits from DataTable.
Also, it can inherit Typed TableBase(Of T) where T is DataRow or a Typed DataRow. I don't use Typed DataRow. It has worse performance (by about 30%) on Table Fill than DataRow, and also needs some tricks to build it.
Next, I create a class for each DataTable that inherits from the base class that contains the common code. In this class, I declare and create each DataColumn for the DataTable.
Now I create the class constructor (New) where I add the columns to Table.Columns and optionally, assign PrimaryKey Columns.
When I have created each Table, I can create a Class for DataSet (Inherits DataSet). Here, I declare and create an instance for each DataTable. Optionally, I declare and create DataRelations. Then in the Constructor, add each table to DataSet.Tables and relations to DataSet.Relations.
Benefits:
- When you load a DataTable, DataAdapter or DataReader don't query the database to get column information.
- You can access Fields by Table.Column declared on Typed DataTable. This is faster than by ColumnName, avoids errors in typing the ColumnName, and has the best support for Refactoring.
- Declare DataTypes for each DataColumn, then you can use DirectCast or TryCast. When you use auto-generated tables based on database information, you need to use Ctype for numeric Columns, a numeric column can use Short, Integer, Long, Double, Decimal...
- You can add functions and overload base methods for each custom Typed DataTable or DataSet.
In the following example code, I wrote a complex function for updating tables on a DataSet with Relations. If the Tables on the database have Relations, then:
I can't Insert a Child Row until Master Row is inserted.
I can't Delete a Master Row until Childs Rows are Deleted.
So, I use a function:
Update( ByVal ParamArray Tables() As RetDataTable )
Here, I put first the Master Table, then the Child Table, then the Child of the Child ...
This is valid for Inserts, but for Deletions, I need do it in reverse order.
Then I put a deleted flag on each Table and do deletions in Tables Reverse Order for each table before sending any other change to database.