我们有一个第三方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捆绑所有源数据并将其传递给函数。
奖金问题 - 假设这项工作完全正常,它是否也适用于多个输入表?
答案 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选项。