2012-11-14 73 views
5

我正在處理由另一個系統維護的數據庫,因此我無法對錶進行任何劇烈更改。這個數據庫中的表格有很多字段(超過30+),沒有兩個表具有相同的命名約定,類型或相同數量的字段。這些表格也會相當頻繁地更改(字段被添加,刪除或更改其類型),並使情況變得更糟。新表也經常創建。現在我確實有一個可以嚴格鍵入的表作爲隊列使用。設計類以應對頻繁的數據庫模式更改

問題:

我必須從給定的表名和該表中一些列的表格中獲取數據。列名作爲字符串提供。由於這些表經常變化,因此很難爲每個表維護嚴格類型的實體。

我該如何設計我的課程,讓他們鬆散耦合,讓我使用這些表格?

感謝您的幫助和抱歉,如果我的解釋糟透了。

+2

從數據庫獲取數據後,您需要如何處理數據?如果你不需要做任何需要輸入的東西,那麼你可以把每一列的內容當作一個字符串。 –

+0

它是SQL Server還是Oracle? –

+3

所以要清楚:你的數據庫模式變化比你的代碼部署更經常?如果是這樣,那是一個......不幸的情況。 –

回答

1

一個想法是使用SQL Management Objects (SMO)和來動態創建強類型。

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); 
    } 
} 

我寫單元測試發電機的數據訪問層這種方式,你可以使用列數據類型補課,如(網上尋找更好的實現 - 在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 

通過這種簡單的ORM,以模式中立的方式連接到數據庫,可以將動態生成的類鬆散地耦合到dB。 .Net 4中新的Dynamic類型似乎是此應用程序的候選多態數據類型。

+1

我標記你的答案是正確的。雖然不是我使用的實現,但您確實帶領我朝着正確的方向,尤其是動態類型。當我得到一個工作示例時,我會發布我的解決方案以供參考。 – slowpython

1

我不確定可以從不穩定的數據中得出什麼樣的業務邏輯。我的假設是你正在做關於記錄相關元數據的一些工作。使用數據聚合(計數,平均數等)而不是實際數據。

我會用一個數據集,使用一個通用的SQL語句,如:

SELECT * FROM {dynamic table name} 
+0

我正在處理實際數據。 DataSet可以在這種情況下工作,但我不確定在這種情況下如何分離工作與數據和使用數據庫。我想在一些依賴注入測試工作,我想這是最終使我困惑的部分。 – slowpython

+0

在我走得更遠之前...有沒有加入? – THBBFT

+0

數據集在單元測試中表現不佳。 – THBBFT

0

的快速修復(而不是解決方案)是使用一個代碼生成工具like this one一個這將更新/創建的類文件根據您的模板或數據庫模式定義本身。通過一點點的工作,這可以通過custom MsBuild task在您的項目中實現完全自動化,這將在您構建項目時運行&您的文件將直接更新到您的解決方案文件夾中。

但最重要的是,當您的表定義更新時,它會在構建時破壞您的代碼 - 顯示由於表定義更改而必須修復的地方。爲此,您的自定義MsBuild任務必須在主構建任務之前運行,如explained here

這對你肯定有好處,讓你更容易,因爲我已經看到這樣的設計有益於類似的項目,但最終'垃圾進出'的原則仍然佔上風,所以上述'修復'只會治療症狀不是可能是糟糕設計的原因,也不是抽象和分析您的解決方案數據所需的內容。因此,你得到一個程序,需要重新編程,以便重新配置:)但對於LOB編程,這並不罕見:)

**注意:如果您決定使用第一個爲了有一個完整的解決方案,您可能需要額外的MsBuild任務,當模式更改時,該任務將自動檢出需要從源代碼管理中更新的文件。如果您需要更多信息,請留下評論。

總結:當您按F5在Visual Studio中構建解決方案時,會發生什麼情況,您的所有類都將使用數據庫中的最新定義進行神奇更新。您還可以限制這種情況發生在Release版本上,以便您在開發過程中每次在Debug模式下構建時都不會完成此操作。

+0

與我的答案類似的想法。代碼生成工具的問題在於你必須編譯代碼,在這個問題中,OP的數據庫改變的不止是代碼。因此,除非Minky分發CSCompiler,否則他/她可能需要接受我的建議並烘烤所有功能以動態地生成類。 –

+0

通過MsBuild編譯代碼是可選的,它將依次調用csc.exe(手動調用csc.exe並不是很容易)。另外我懷疑只有.NET開發人員會開發他的應用程序,所以MsBuild&csc編譯器將會出現。 – user1416420