Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designing classes to cope with frequent database schema changes

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.

like image 769
slowpython Avatar asked Nov 04 '22 11:11

slowpython


2 Answers

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.

like image 182
Jeremy Thompson Avatar answered Nov 13 '22 15:11

Jeremy Thompson


I'm not really sure what sort of business logic you can derive from unstable data. My assumption is that you are doing some work on the meta data associated with the records. Working with the aggregates of the data (counts, averages, etc) rather then actual data.

I would use a DataSet, use a generic SQL statement like:

SELECT * FROM {dynamic table name}
like image 31
THBBFT Avatar answered Nov 13 '22 15:11

THBBFT