从C#验证表类型是否正确

时间:2011-05-17 09:19:00

标签: c# unit-testing sql-server-2008

我在我的数据库中创建了一些表类型,用作存储过程参数。这些对应于真实的数据库表,因此如果它们不同步则会出现问题。我想添加一个单元测试来查看两者,如果它们不同则会失败,但我不知道从哪里开始。

我不知道是否有推荐的方法来做到这一点 - 我试图以某种方式提取列信息,循环通过它并且如果它们不同则无法通过测试,但它似乎有点繁琐。

有更好的方法吗?

2 个答案:

答案 0 :(得分: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

如果没有返回任何行,则类型和表格相同。

答案 1 :(得分:1)

就像你说的那样,使用C#,你必须将两个表中的数据转储到单独的DataSet中,然后循环并进行比较。这可能是一种资源浪费,如果你有数千条记录,很可能会产生非常不理想的表现。

你必须用C#做吗?为什么不在SQL中进行比较并返回结果的bool(如果一切都相同,则为true,如果存在差异则为false)?

但如果你必须在.NET中这样做,你有没有尝试过研究F#?我一直在做一些阅读,看起来F#可能会在C#之上进行这种数据分析的性能提升。

这篇文章可以帮助您使用F#和SQL http://tomasp.net/blog/dynamic-sql.aspx

或者,您可以查看LINQ(抱歉,我对此缺乏经验),它可能是您正在寻找的答案。 http://www.linqpad.net/WhyLINQBeatsSQL.aspx