2011-05-17 40 views
3

我在我的數據庫中創建了幾個表類型,用作存儲過程參數。這些對應於真正的數據庫表,所以如果它們不同步,就會出現問題。我想添加一個單元測試,看看這兩者,如果它們不同,就會失敗,但我不確定從哪裏開始。驗證表類型是否正確來自C#

我不知道是否有推薦的方法來做到這一點 - 我會試圖以某種方式拉出列信息,循環通過它,並通過測試,如果他們不同,但似乎有點fiddly 。

有沒有更好的方法?

+1

對不起,表格類型是什麼意思? 您是否在比較數據庫中的兩個表? 或者你是否試圖比較只存在於C#方面的數據? 或者您是否試圖將存在於C#上的一組數據與數據庫中存在的表進行比較? – Kukoy 2011-05-19 13:43:12

+0

這是我在做什麼: CREATE TYPE MyTableType AS TABLE ([Column definitions ...]) 這是我的實際MyTable表的鏡像,我可以在批量更新中使用它作爲表值參數(http://msdn.microsoft.com/en-us/library/bb510489.aspx)。我想要做的是在C#中編寫一個測試,將MyTableType與MyTable逐列比較。我想這與比較兩個實際表格非常相似。 – Alex 2011-05-19 14:14:08

+0

爲了澄清,你說的是表結構(列名和列類型),不一定是數據,對不對? – 2011-05-19 15:13:19

回答

2

對於SQL Server 2008,看看在sys.tablessys.table_typessys.columns系統表。

在我的數據庫之一,我有一個表類型,稱爲candidateRoutes和物理(實際)表稱爲RouteArea

以下兩個查詢:

select sys.columns.* from sys.table_types join sys.columns on sys.columns.object_id = sys.table_types.type_table_object_id where sys.table_types.name = 'candidateRoutes' 
select sys.columns.* from sys.tables join sys.columns on sys.columns.object_id = sys.tables.object_id where sys.tables.name = 'RouteArea' 

回報:

object_id name  column_id system_type_id user_type_id max_length precision scale collation_name is_nullable is_ansi_padded is_rowguidcol is_identity is_computed is_filestream is_replicated is_non_sql_subscribed is_merge_published is_dts_replicated is_xml_document xml_collection_id default_object_id rule_object_id is_sparse is_column_set 
215671816 RouteId 1   56    56   4   10   0  NULL   0   0     0    0   0   0    0    0      0     0     0    0     0     0    0   0 
215671816 Area  2   240    130   -1   0   0  NULL   0   0     0    0   0   0    0    0      0     0     0    0     0     0    0   0 

object_id name  column_id system_type_id user_type_id max_length precision scale collation_name is_nullable is_ansi_padded is_rowguidcol is_identity is_computed is_filestream is_replicated is_non_sql_subscribed is_merge_published is_dts_replicated is_xml_document xml_collection_id default_object_id rule_object_id is_sparse is_column_set 
1675153013 RouteId 1   127    127   8   19   0  NULL   0   0    0    0   0   0    0    0      0     0     0    0     0     0    0   0 
1675153013 ValidFrom 2   61    61   8   23   3  NULL   0   0    0    0   0   0    0    0      0     0     0    0     0     0    0   0 
1675153013 ValidTo 3   61    61   8   23   3  NULL   1   0    0    0   0   0    0    0      0     0     0    0     0     0    0   0 
1675153013 Line  4   240    130   -1   0   0  NULL   0   0    0    0   0   0    0    0      0     0     0    0     0     0    0   0 
1675153013 Area  5   240    130   -1   0   0  NULL   1   0    0    0   0   0    0    0      0     0     0    0     0     0    0   0 

,所以你也許可以做這樣的事情:

with 
    TableType as 
     (select name, user_type_id, max_length, precision from sys.columns where object_id = (select type_table_object_id from sys.table_types where name = 'candidateRoutes')), 
    PhysicalTable as 
     (select name, user_type_id, max_length, precision from sys.columns where object_id = (select object_id from sys.tables where name = 'RouteArea')) 
    select * from TableType full join PhysicalTable 
     on TableType.name = PhysicalTable.name 
    where TableType.name is null 
     or PhysicalTable.name is null 
     or TableType.user_type_id <> PhysicalTable.user_type_id 
     or TableType.max_length <> PhysicalTable.max_length 
     or TableType.precision <> PhysicalTable.precision 

但包括scale, collation_name, is_nullable等,發現做匹配的所有列。在我的情況下,我得到:

name  user_type_id max_length precision name  user_type_id max_length precision 
RouteId 56   4   10   RouteId 127   8   19 
NULL  NULL   NULL  NULL  ValidFrom 61   8   23 
NULL  NULL   NULL  NULL  ValidTo 61   8   23 
NULL  NULL   NULL  NULL  Line  130   -1   0 

如果沒有行返回,類型和表是相同的。

+0

謝謝Gavin。你的最後一個查詢的where子句 - 爲什麼'where TableType.name是null ...'?如果任何列都有名字,是不是返回0行?看起來像是我想要的第一步,儘管 – Alex 2011-05-20 08:55:51

+0

@Alex:我在'TableType'和'PhysicalTable'上做了一個'full join',這樣就可以顯示'TableType'中存在的所有列名稱,即使'PhysicalTable'中沒有相應的列,反之亦然。這兩個檢查'名稱是空',然後將結果限制爲只存在於一個表或另一個表中的列。例如,'PhysicalFrom'存在於'PhysicalTable'中,但'TableType'中不存在,因此'TableType.name'爲null。如果在where子句中只使用這兩個條件,則基本上可以看到任何一個表中存在的所有列,但在另一個表中卻缺失了其他條件... – 2011-05-23 12:10:02

+0

... where子句中的其餘條件包括_both_表中存在的所有列,但有不同的類型。 – 2011-05-23 12:10:40

1

就像你說的那樣,用C#,你必須將兩個表中的數據轉儲到不同的DataSet中,然後循環和比較。如果你有成千上萬的記錄,那麼這將是一個巨大的資源浪費,並且很可能會產生非常不理想的表現。

你必須在C#中完成嗎?你爲什麼不在SQL中進行比較並返回一個結果布爾(如果一切都是一樣的,如果有差異則返回false)?

但是,如果你必須在.NET中做到這一點,你試過看着F#嗎?我一直在做一些閱讀,看起來F#可能是C#之上的一種性能改進,用於這種數據分析。

這裏有一篇文章可以幫助你處理F#和SQL。或者,你可以看看LINQ(對不起,我對它沒有經驗),它可能是你正在尋找的東西的答案。 http://www.linqpad.net/WhyLINQBeatsSQL.aspx

+0

+1既然你和Gavin建議,我試圖創建一個存儲過程將在SQL服務器上運行,然後將成功/失敗返回給我的C#代碼 – Alex 2011-05-24 09:10:40

相關問題