将表作为参数传递给SQLCLR TV-UDF

我们有一个第三方DLL可以在DataTable上运行源信息并生成一些有用的值,我们试图通过SQLCLR将其连接起来,以便在SQL Server 2008中作为表值UDF进行调用。

将这个概念更进一步,我想编写一个CLR表值函数 ,它对来自DB的源数据表进行操作。

我很确定我理解在T-SQL方面需要做些什么; 但是, .NET(C#)代码中的方法签名应该是什么样的? “来自SQL Server的表数据?”的参数数据类型是什么?

例如

/* Setup */ CREATE TYPE InTableType AS TABLE (LocationName VARCHAR(50), Lat FLOAT, Lon FLOAT) GO CREATE TYPE OutTableType AS TABLE (LocationName VARCHAR(50), NeighborName VARCHAR(50), Distance FLOAT) GO CREATE ASSEMBLY myCLRAssembly FROM 'D:\assemblies\myCLR_UDFs.dll' WITH PERMISSION_SET = EXTERNAL_ACCESS GO CREATE FUNCTION GetDistances(@locations InTableType) RETURNS OutTableType AS EXTERNAL NAME myCLRAssembly.GeoDistance.SQLCLRInitMethod GO /* Execution */ DECLARE @myTable InTableType INSERT INTO @myTable(LocationName, Lat, Lon) VALUES('aaa', -50.0, -20.0) INSERT INTO @myTable(LocationName, Lat, Lon) VALUES('bbb', -20.0, -50.0) SELECT * FROM @myTable DECLARE @myResult OutTableType INSERT INTO @myResult GetDistances @myTable /* SQLCLR Call: GeoDistance.SQLCLRInitMethod(@myTable) */ 

lat / lon – > distance是一个愚蠢的例子,当然应该在SQL中更好地处理; 但我希望它通过与SQLCLR程序集绑定的表值UDF来说明table-in – > table-out的一般意图。

我不确定这是可能的; SQLCLRInitMethod方法签名在C#中会是什么样的?

 public class GeoDistance { [SqlFunction(FillRowMethodName = "FillRow")] public static IEnumerable SQLCLRInitMethod( myInputData) { //... } public static void FillRow(...) { //... } } 

如果不可能,我知道我可以在C#代码中使用“context connection = true”SQL连接, 让CLR组件在给定相关密钥的情况下查询必要的数据 ; 但这对数据库架构的变化很敏感。 所以我希望让SQL捆绑所有源数据并将其传递给函数。

奖金问题 – 假设这完全有效,它是否也适用于多个输入表?

原来在SQLCLR函数上有一个固定的有效输入列表,由.NET数据类型和SQL数据类型之间的可用映射决定

SQL数据类型“表”被明确调出为没有通过CLR的映射

因此,不可能将表值数据INTO传递给表值CLR函数作为方法参数。

备择方案

似乎可以通过select ... for xml获取表格数据, select ... for xml扭曲以提供给SqlXml参数。

我已经成功使用了SqlConnection conn = new SqlConnection("context connection = true"); 在.NET代码中让TVF向DB查询它需要的表格数据。

这个问题似乎(大部分)与以下内容重复:

CLR具有数组参数的表值函数

作为一个简单的说明,我在这个问题中建议:分隔列表,XML或CLR UDT。

还可以选择填充表格并在函数中从中加载DataTable。 可能不建议使用真正的表,因为它需要额外的努力才能使其“线程安全”(不与其他SPID交叉数据)并且需要额外的清理过程,因为函数将无法执行DML完成数据后清除它的声明。 在某些情况下,这可能是首选,但可能不适用于这种特殊情况。 幸运的是,临时表可以在SQLCLR函数访问(作为只读,但在T-SQL函数中根本无法访问它们)。 使用临时表具有与使用永久表相同的优点,但不具有与其他SPID冲突或需要单独清理的缺点。 唯一的要求是您使用Context Connection,因为这是访问基于会话的对象(即临时表)的唯一方法。

因此,对于这种特殊情况,我建议尝试使用Temp Table或XML选项。