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

时间:2010-06-09 18:43:50

标签: c# sql-server-2008 sqlclr user-defined-functions

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

将概念here更进一步,我想编写一个CLR Table-Valued Function来对数据库中的源数据表进行操作。

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

e.g。

/* 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 - >距离事物是一个愚蠢的例子,当然应该在SQL中更好地处理;但我希望它说明了table-in的一般意图 - >通过与SQLCLR程序集绑定的表值UDF进行表格输出。

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

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

    public static void FillRow(...)
    {
      //...
    }
}

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

奖金问题 - 假设这项工作完全正常,它是否也适用于多个输入表?

2 个答案:

答案 0 :(得分:9)

原来在SQLCLR函数上有一个固定的有效输入列表,由可用的mapping between .NET datatypes and SQL datatypes确定

SQL数据类型“table”被明确地称为通过CLR具有无映射

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

<强>替代

似乎可以通过select ... for xml扭曲获取表格数据,以便输入SqlXml参数。

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

答案 1 :(得分:3)

这个问题似乎(大部分)是重复的:

CLR Table-valued function with array argument

快速说明,在这个问题中,我建议:分隔列表,XML或CLR UDT。

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

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