单元测试 - 验证 C# 中的表类型是否正确
本文关键字:类型 是否 验证 单元测试 | 更新日期: 2023-09-27 17:56:45
我在数据库中创建了几个表类型来用作存储过程参数。这些对应于真实的数据库表,因此如果它们不同步,就会出现问题。我想添加一个单元测试,该测试查看两者并在它们不同时失败,但我不确定从哪里开始。
我不知道是否有推荐的方法可以做到这一点 - 我将尝试以某种方式提取列信息,循环遍历它并在它们不同时无法通过测试,但这似乎有点繁琐。
有没有更好的方法?
对于 SQL Server 2008,请查看系统表sys.tables
、sys.table_types
和sys.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
如果未返回任何行,则类型和表相同。
正如您所说,使用 C#,您必须将两个表中的数据转储到单独的数据集中,然后循环和比较。 不过,这将是一个资源消耗者,如果你有数千条记录,很可能会产生非常不理想的性能。
你必须在 C# 中执行此操作吗? 你为什么不在SQL中进行比较并返回一个结果的布尔值(如果一切都一样,则为true,如果存在差异,则为false)?
但是,如果必须在 .NET 中执行此操作,是否尝试过查看 F#? 我一直在做一些阅读,看起来 F# 可能是这种数据分析在 C# 之上的性能改进。
下面是一篇可能对 F# 和 SQL 有所帮助的文章。
http://tomasp.net/blog/dynamic-sql.aspx
或者,你可以看看 LINQ(对不起,我对此没有经验),它可能是你正在寻找的答案。http://www.linqpad.net/WhyLINQBeatsSQL.aspx