2012-11-14 37 views
5

Ich arbeite an einer Datenbank, die von einem anderen System verwaltet wird, so dass ich keine drastischen Änderungen an den Tabellen vornehmen kann. Die Tabellen in dieser Datenbank haben ziemlich viele Felder (über 30+), ohne dass zwei Tabellen dieselbe Namenskonvention, dieselben Typen oder dieselbe Anzahl von Feldern haben. Diese Tabellen ändern sich ebenfalls ziemlich häufig (Felder werden hinzugefügt, entfernt oder ihre Typen werden geändert). Außerdem werden häufig neue Tabellen erstellt. Jetzt habe ich eine Tabelle, die streng typisiert werden kann und die als Warteschlange verwendet wird.Entwerfen von Klassen für häufige Datenbankschemaänderungen

Das Problem:

Ich habe Daten aus einer Tabelle der Tabellennamen und einige Spalten in dieser Tabelle angegeben zu bekommen. Die Spaltennamen werden als Strings bereitgestellt. Da sich diese Tabellen so oft ändern, wird es schwierig, streng typisierte Entitäten für jede Tabelle zu erhalten.

Wie würde ich meine Kurse so gestalten, dass sie lose miteinander verbunden sind, aber mir erlauben, mit diesen Tabellen zu arbeiten?

Danke für die Hilfe und tut mir leid, wenn meine Erklärung saugt.

+2

Was müssen Sie mit den Daten tun, sobald Sie sie aus der DB bekommen? Wenn Sie nichts tun müssen, was eine Eingabe erfordert, können Sie den Inhalt jeder Spalte als Zeichenfolge behandeln. –

+0

Ist es SQL Server oder Oracle? –

+3

Um es klar zu stellen: Ihr Datenbankschema ändert sich regelmäßiger als Ihr Code implementiert wird? Wenn ja, ist das eine ... unglückliche Situation. –

Antwort

1

Eine Idee ist, SQL Management Objects (SMO) mit zu verwenden, um starke Typen dynamisch zu erstellen.

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 Unit-Test-Generatoren für Data Access Layer auf diese Weise geschrieben haben, und man konnte Klassen mit Hilfe der Datentypen von Spalten bilden, zB (schauen Sie online für eine bessere Umsetzung - 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 

Mit diesem einfachen ORM, das sich schemenneutral mit Ihrer Datenbank verbindet, können Sie dynamisch generierte Klassen an den dB koppeln. Der neue Typ Dynamic in .Net 4 scheint ein guter polymorpher Datentypkandidat für diese Anwendung zu sein.

+1

Ich habe Ihre Antwort als richtig markiert. Obwohl nicht die Implementierung, die ich verwendet habe, hast du mich in die richtige Richtung vor allem mit dem dynamischen Typ geführt. Wenn ich ein Arbeitsbeispiel bekomme, werde ich meine Lösung als Referenz veröffentlichen. – slowpython

1

Ich bin nicht wirklich sicher, welche Art von Geschäftslogik Sie aus instabilen Daten ableiten können. Ich gehe davon aus, dass Sie an den Metadaten arbeiten, die den Datensätzen zugeordnet sind. Arbeiten mit den Aggregaten der Daten (Zählungen, Mittelwerte, etc.) statt tatsächlicher Daten.

würde ich einen DataSet verwenden, verwenden Sie eine generische SQL-Anweisung:

SELECT * FROM {dynamic table name} 
+0

Ich arbeite mit den tatsächlichen Daten. Ein DataSet würde in diesem Fall funktionieren, aber ich bin mir einfach nicht sicher, wie man das Arbeiten mit den Daten trennt und in diesem Fall mit der Datenbank arbeitet. Ich würde gerne in einer Abhängigkeitsinjektion zum Testen arbeiten, ich denke, das ist der Teil, der mich am Ende verwirrt. – slowpython

+0

Bevor ich weiter gehe ... sind da Joins involviert? – THBBFT

+0

Und DataSets spielen nicht gut mit Komponententests. – THBBFT

0

Eine schnelle Lösung (keine Lösung) wäre ein Code-Generierung Dienstprogramm verwenden like this one eine, die Ihre Klassendateien würde aktualisieren/erstellen basierend auf Ihren Vorlagen oder den Schemadefinitionen des Datenverzeichnisses selbst. Mit ein wenig Arbeit könnte dies in Ihrem Projekt über custom MsBuild task vollständig automatisiert werden, die ausgeführt würden, wenn Sie Ihr Projekt & erstellen Ihre Dateien würden direkt in Ihrem Lösungsordner aktualisiert werden.

Aber vor allem würde es Ihren Code beim Build brechen, wenn Ihre Tabellen-Definitionen aktualisiert werden - zeigen Sie, wo Sie Dinge aufgrund von Änderungen der Tabellendefinition beheben müssen. Damit dies funktioniert, muss Ihre benutzerdefinierte MsBuild-Task vor der Haupt-Build-Task als explained here ausgeführt werden.

Dies würde definitiv Ihnen nützen und die Dinge leicht für Sie machen, weil ich gesehen habe, dass ein solches Design von einem ähnlichen Projekt profitiert, aber am Ende würde das "Mist-In-Mist-Prinzip" immer noch vorherrschen Behandeln Sie das Symptom nicht die Ursache, die wahrscheinlich ein schlechtes Design ist und keine Abstraktion und Analyse dessen, was Ihre Lösungsdaten benötigen, ist. Daher erhalten Sie ein Programm, das neu programmiert werden muss, um es neu zu konfigurieren :) aber für die LOB-Programmierung ist es nicht ungewöhnlich :)

** Hinweis: Wenn Sie sich entscheiden, das in der ersten beschriebene Design zu verwenden Um eine vollständige Lösung zu erhalten, benötigen Sie möglicherweise eine zusätzliche MsBuild-Aufgabe, die automatisch die Dateien auscheckt, die bei Änderung des Schemas von Ihrer Quellcodeverwaltung aktualisiert werden müssen. Kommentar unten, wenn Sie weitere Informationen dazu benötigen.

Zusammengefasst: was passieren wird, ist, wenn Ihre Presse F5 Ihre Lösung in Visual Studio all Klassen auf magische Weise mit den neuesten Definitionen aus der Datenbank aktualisiert werden zu bauen. Sie können dies auch auf Release Builds beschränken, so dass Sie dies nicht jedes Mal, wenn Sie in Debug Modus erstellen, während Sie entwickeln.

+0

Ähnliche Idee zu meiner Antwort. Das Problem mit einem Dienstprogramm zur Codegenerierung besteht darin, dass Sie den Code kompilieren müssen, und in dieser Frage ändert sich die Datenbank des OPs mehr als der Code. Daher, wenn Minky den CSCompiler nicht verteilt, wird er/sie wahrscheinlich meinen Ratschlag befolgen und in all der Funktionalität backen müssen, um dynamisch Klassen on-the-fly zu generieren. –

+0

Compilierung des Codes ist optional über MsBuild, die wiederum csc.exe aufrufen würde (es ist nicht sehr einfach, csc.exe manuell aufzurufen). Außerdem vermute ich, dass nur .NET-Entwickler seine Anwendung entwickeln werden, so dass MsBuild und der csc-Compiler vorhanden sind. – user1416420

Verwandte Themen