17

这个来自 SQL Server 2008 BOL的页面讨论了 CLR 存储过程,并有一个标记为“表值参数”的部分,其中讨论了它们如何具有优势。太好了 - 我很想在我的 CLR procs 中使用 TVP,但不幸的是,这似乎是宇宙中唯一提到这种可能性的参考,并且该部分没有描述语法是什么(也没有进一步的信息链接在段落末尾)

当然,我可以很容易地找到关于如何从 T-SQL 过程中使用 TVP 的描述,或者一般来说如何执行 CLR 过程。但是编写一个需要 TVP 的 CLR proc?没有。这都是非常不常用的,因为将多行数据传递到存储过程是一个流行的问题。

这让我想知道该页面上的部分是否存在错误。有人请告诉我不是,并指出更多信息/示例。

[编辑]

当我遇到这个时,我也正准备将这个发布到一个 MS 论坛,这似乎是棺材上的最后一颗钉子。看来是做不到了。

4

5 回答 5

5

我可以找到更多 参考资料。但是,这些都是为了将​​表值参数传递给 TSQL 过程,所以用处不大。

但是,我得出的结论是,这是不可能的。首先,有CLR 和 SQL 类型之间的映射列表。对于表类型,没有映射,因此以下内容不起作用,例如:

[SqlProcedure]
public static void StoredProcedure(DataTable tvp, out int sum)
{
    return 42;
}

进而

CREATE TYPE MyTableType AS TABLE 
(
    Id INT NOT NULL PRIMARY KEY,
    [Count] INT NOT NULL
)
GO
CREATE ASSEMBLY ClrTest FROM '<somePath>'
GO
CREATE PROCEDURE ClrTest
AS EXTERNAL NAME ClrTest.StoredProcedures.StoredProcedure
GO

无论您尝试何种类型 ( DataTable, DbDataReader, IEnumerable),CREATE PROCEDURE调用都会不断生成错误 6552: CREATE PROCEDURE for "ClrTest" 失败,因为参数 "@tvp" 的 T-SQL 和 CLR 类型不匹配。

其次,您链接到的页面上的文档说:用户定义的表类型不能作为表值参数传递给在 SQL Server 进程中执行的托管存储过程或函数,也不能从其返回。

我似乎无法在任何地方找到如何在 C# 中创建用户定义的表类型,但这似乎也是一个死胡同。

也许您可以在 Microsoft 论坛的某个地方提出您的问题。他们在 CLR sproc 页面上提到表值参数但从未解释如何实现这一点仍然很奇怪。如果您找到任何解决方案,我想知道。

于 2009-08-31T11:24:32.657 回答
4

您可以使用在调用过程之前创建和填充的临时表,并在 clr 过程中读取该表。

于 2012-07-04T14:25:47.707 回答
2

解决方案是将您的表格数据序列化为 Json 格式的字符串,然后将该字符串传递到您的 CLR proc。在您的 clr proc 或函数中,您可以将 json 解析为 IEnumerable、列表或表格对象。然后,您可以像处理任何其他类型的表格数据一样处理数据。

我编写了一些实用程序,能够将任何 sql 表序列化为 Json 格式的字符串。我很乐意与任何提供电子邮件地址的人分享它们。Phil Factor 编写了一个很好的 T-SQL Json 解析器,他称之为 parseJson。我已经将他的解决方案改编为执行速度更快的 clr。两者都接受 Json 格式的字符串并从该字符串生成一个表。我还使用了多种 Json 实用程序,用于 T-SQL 和 CLR,它们能够序列化、解析、插入、删除和更新存储在 sql 列中的 Json 格式字符串。

于 2011-10-23T21:02:44.667 回答
2

如果您使用 C#(相对于缺少自定义迭代器的 VB),您可以编写 ADO.NET 代码来调用 ExecuteNonQuery() 并运行带有SqlDbType.Structured参数的存储过程(即 TVP)。

作为 TVP 的值传递的集合必须实现IEnumerable<SqlDataRecord>。每次执行此 IEnumerable 的yield return时,SqlDataRecord “row” 被流水线化到 “table” 参数。

有关详细信息,请参阅本文

于 2012-07-13T18:11:43.157 回答
1

虽然目前看起来直接将表传递给 CLR 过程是不可能的,但我得到了一个结果,尽管它是次优的:

  • 定义一个 TSQL 表值 UDT FooTable
  • 定义一个以 FooTable 作为参数并使用 FOR XML EXPLICIT 返回 XML 的 TSQL 函数
  • 将生成的 XML 传递给 CLR 函数/过程而不是表本身

不理想,但它变得更接近了。

于 2011-09-22T11:01:11.847 回答