【问题标题】:Retrieve UDT table structure in VB.NET在 VB.NET 中检索 UDT 表结构
【发布时间】:2014-10-28 12:47:10
【问题描述】:

在寻找我的答案时,我看到了这个问题: ADO.NET Retrieve UDT Columns from SQL Server 2012? 但仍未得到答复。简而言之,这是我的问题,但上下文如下。

我有一个 SQL Server 2012 存储过程,它接受两个表值参数 (TVP),我想从 VB.NET 调用它们(现在是 3.5,但我没有与之结婚)。我已经使用SqlCommandBuilder.DeriveParameters 来确定我的存储过程的参数:

cmd1 = New SqlCommand()
cmd1.Connection = oCn2 ' assume properly connected to database
cmd1.CommandText = "uspInsertTestData"
cmd1.CommandType = CommandType.StoredProcedure
SqlCommandBuilder.DeriveParameters(cmd1)

我的存储过程如下所示:

ALTER Procedure [dbo].[uspInsertTestData]
        @Processor varchar(20),
        @TRes [dbo].[TestResultsType] READONLY,
        @EXSetup ExtraTestSetupType READONLY,
        @ErrNum int OUTPUT,
        @ErrString varchar(300) OUTPUT
AS
BEGIN
-- ... stuff
END

我的 UDT 表类型如下所示:

CREATE TYPE [dbo].[TestResultsType] AS TABLE(
    [ResultValue] [sql_variant] NULL,
    [ResultInfo] [varchar](50) NULL,
    [ResultUnits] [char](20) NULL,
    [PassedTest] [varchar](15) NULL,
    [TestName] [varchar](30) NULL,
    [TestTypeName] [varchar](50) NULL,
    [MinLimit] [float] NULL,
    [MaxLimit] [float] NULL,
    [UUTTemperature] [float] NULL)

CREATE TYPE [dbo].[ExtraTestSetupType] AS TABLE(
    [FieldName] [varchar](50) NULL,
    [FieldValue] [varchar](50) NULL,
    [Units] [char](20) NULL)

DeriveParameters() 的调用按预期填充cmd1.Parameters,我也可以识别这两种UDT 表类型——Parameters.TypeName 表明它们实际上是UDT 表类型——这段代码:

Debug.Print("parameter [" & p.ParameterName & "]: SqlDbType=[" & _
      p.SqlDbType().ToString() & "]: TypeName=[" & p.TypeName() & "])

产量:

parameter [@Processor]: SqlDbType=[VarChar]: TypeName=[]
parameter [@TRes]: SqlDbType=[Structured]: TypeName=[LMUTesterData.dbo.TestResultsType]
parameter [@EXSetup]: SqlDbType=[Structured]: TypeName=[LMUTesterData.dbo.ExtraTestSetupType]
parameter [@ErrNum]: SqlDbType=[Int]: TypeName=[]
parameter [@ErrString]: SqlDbType=[VarChar]: TypeName=[]

说了这么多,问题是:

1: 有没有办法导出 UDT 表类型的列?我研究过的所有示例都将使用DataTable.Columns.Add() 将COLUMNS 添加到数据表中,然后再将它们作为参数传递给存储过程。理想情况下,我想使用 Parameter.TypeName 值来检索 UDT 的结构。

2:如果对 1 的回答是“否”,当我使用DataTable.Columns.Add() 构建我的 UDT 的结构时,它是否必须与 UDT 本身的顺序相同?鉴于上面 TestResultstype 的 UDT 定义,是否可以这样做:

DataTable dataTable = new DataTable("TestResultsType"); 
dataTable.Columns.Add("ResultUnits", GetType(string)); 
dataTable.Columns.Add("ResultInfo", GetType(string)); 
dataTable.Columns.Add("ResultValue", GetType(float)); 
dataTable.Columns.Add("TestTypeName", GetType(string)); 
dataTable.Columns.Add("UUTTemperature", GetType(float)); 
dataTable.Columns.Add("MinLimit", GetType(float)); 
dataTable.Columns.Add("MaxLimit", GetType(float)); 

3:这样做的唯一方法是实现为 CLR(公共语言运行时)程序集吗?

【问题讨论】:

    标签: sql-server vb.net stored-procedures sql-server-2012 user-defined-types


    【解决方案1】:
    Private Function DataTableForServerType(ByVal Connection As SqlConnection, ByVal ServerTypeName As String) As DataTable
    
        Dim SanitisedQualifiedTypeName As String
    
        Using cmd = New SqlCommand()
            cmd.Connection = Connection
            cmd.CommandType = CommandType.Text
            cmd.CommandText = "select top (1) quotename(schema_name([schema_id]), '[') + N'.' + quotename([name], '[') from [sys].[types] where [name] = parsename(@type_name,1) and [schema_id] = isnull(schema_id(parsename(@type_name,2)), [schema_id]) and [is_table_type] = 1;"
            cmd.Parameters.Add("@type_name", SqlDbType.NVarChar, 128).Value = ServerTypeName
    
            SanitisedQualifiedTypeName = CType(cmd.ExecuteScalar(), String)
    
            If String.IsNullOrEmpty(SanitisedQualifiedTypeName) Then
                Throw New Exception(String.Format("Table type '{0}' does not exist or you don't have permission.", ServerTypeName))
            End If
        End Using
    
    
        Using ada = New SqlDataAdapter("declare @t " & SanitisedQualifiedTypeName & "; select * from @t;", Connection)
            Dim res As New DataTable
    
            ada.Fill(res)
    
            Return res
        End Using
    
    End Function
    

    【讨论】:

    • 非常感谢!非常适合我的需要!
    • 一个有趣的注意事项 - 在尝试从 VB.NET 填充时,在 UDT 表中使用 sql_variant 不起作用。我必须将 UDT 更改为 varchar(50),然后在加载到表时使用 CONVERT(ResultValue, sql_variant)。
    • @KeithKibler 是的,it would appear so
    猜你喜欢
    • 2017-08-24
    • 1970-01-01
    • 2014-03-21
    • 1970-01-01
    • 2022-08-23
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 2016-12-25
    相关资源
    最近更新 更多