I am working on a database that is maintained by another system, so I am unable to make any drastic changes to the tables. The tables in this database have quite a few fields (upwards of 30+) with no two tables having the same naming convention, types, or same number of fields. These tables also change fairly frequently (fields being added, removed or their types being changed) and to make matters worse new tables are created on a frequent basis as well. Now I do have one table that can be strictly typed which is used as a queue.
The problem:
I have to get data from a table given the table name and some columns in that table. The column names are supplied as strings. Since these tables change so often it becomes difficult to maintain strictly typed entities for each table.
How would I design my classes in a way that they are loosely coupled but allow me to work with these tables?
Thanks for the help and sorry if my explanation sucks.
One idea is to use SQL Management Objects (SMO) with Tables to dynamically create strong types.
Server srv = new Server(conn);
Database db = srv.Databases["AdventureWorks"];
foreach (Table table in db.Tables)
{
Console.WriteLine(" " + table.Name);
foreach (Column col in table.Columns)
{
Console.WriteLine(" " + col.Name + " " + col.DataType.Name);
}
}
I've written unit test generators for Data Access Layers this way and you could make up Classes using the column DataTypes, eg (look online for a better implementation - in C#):
Public Function SQLParameterType(ByVal ParameterDataType As String) As String
ParameterDataType = ParameterDataType.ToUpper
If ParameterDataType.IndexOf("NVARCHAR") > 0 Then
Return "string"
ElseIf ParameterDataType.IndexOf("VARCHAR") > 0 Then
Return "string"
End If
Select Case ParameterDataType
Case Is = "BIGINT"
Return "Int64"
Case Is = "INT"
Return "Int32"
Case Is = "SMALLINT"
Return "Int16"
Case Is = "BIT"
If gIsVBdotNet Then
Return "boolean"
Else
Return "bool"
End If
Case Is = "DATETIME"
Return "DateTime"
Case Is = "DATETIME2"
Return "DateTime"
Case Is = "SMALLDATETIME"
Return "DateTime"
Case Is = "MONEY"
Return "single" 'float
Case Is = "FLOAT"
Return "single" 'float
Case Is = "REAL"
Return "double"
'Case Is = "INT"
' Return "int32"
'Case Is = "INT"
' Return "int32"
Case Else
Return "666"
End Select
End Function
With this simple ORM that connects to your database in a schema-neutral way you can loosely couple dynamically generated classes to the dB. The new Dynamic type in .Net 4 seems to be a good polymorphic datatype candidate for this application.