【问题标题】:Create MS SQL Server function from dll assembly with ref parameter使用 ref 参数从 dll 程序集创建 MS SQL Server 函数
【发布时间】:2020-06-11 12:40:21
【问题描述】:

我想从已成功注册到 MS SQL Server 数据库中的 C# 库作为程序集创建一个函数。该函数在 C# 中的签名如下所示:

public static double DensityD11162Relative(double observedDensity, 
                                           double observedTemperature, 
                                           double observedPressure, 
                                           ref int errorCode)

为了在 SQL Server 中使用此函数,我尝试按如下方式创建函数:

CREATE FUNCTION DensityD11162Relative(@observedDensity float, 
                                    @observedTemperature float,
                                    @observedPressure float,
                                    @errorCode int) 
    RETURNS float
    AS
    EXTERNAL NAME [Flowcal.ApiVcfLibrary].[Flowcal.ApiVcfLibrary.Customary.Original.Lubricants].DensityD11162Relative

但是,这会导致以下错误消息:

Msg 6580, Level 16, State 1, Procedure DensityD11162Relative, Line 3 [Batch Start Line 0]
Declarations do not match for parameter 4. .NET Framework reference and T-SQL OUTPUT parameter declarations must match.
Msg 6552, Level 16, State 3, Procedure DensityD11162Relative, Line 3 [Batch Start Line 0]
CREATE FUNCTION for "DensityD11162Relative" failed because T-SQL and CLR types for parameter "@errorCode" do not match.

消息指出第四个参数的类型错误,这是有道理的,因为 C# 签名表明它需要一个 ref int 参数。 我的问题是:从程序集创建 SQL 函数时,我可以传递 ref 参数(或占位符)吗?如果是这样,怎么做?如果没有,是否有任何方法可以在不使用 C# 编写包装器的情况下解决此问题?

我使用的是 SQL Server 2017

【问题讨论】:

  • 您大概应该将其声明为@errorCode int OUTPUT 以允许对其进行与 by-ref 类似的处理。
  • 不幸的是,这是不允许的:消息 181,级别 15,状态 1,过程 DensityD11162Relative,第 6 行 [Batch Start Line 0] 无法在 DECLARE、CREATE AGGREGATE 或 CREATE FUNCTION 语句中使用 OUTPUT 选项。
  • 函数不能有输出参数。所以你知道答案了——你不能直接把它作为一个函数来实现。
  • 太糟糕了,我想我们将不得不编写一个包装器。谢谢大家的帮助。

标签: c# sql sql-server clr sql-function


【解决方案1】:

由于您似乎可以控制 DLL 和函数,因此您可以删除 ErrorCode 的 ref 参数,并从您的方法中返回一个字符串,其中包含以下内容:

double|errorCode 

然后在 SQL 中,您可以拆分字符串结果并在客户端将其转换为 float 和 int。

(我知道有一种更有效的写法,每一步都更清楚)

Declare @StringResult nvarchar(50)
Declare @Result float
Declare @Delimiter nvarchar(1)
Declare @SeperateIndex int
Declare @ErrorCode int

Set @Delimiter = '|'

-- Example return value
Set @StringResult = '50|-1100'

Set @SeperateIndex = CharIndex(@Delimiter,@StringResult)

Set @Result = Convert(float,Substring(@StringResult,0,@SeperateIndex))
Set @ErrorCode = Convert(int, Substring(@StringResult, @SeperateIndex + 1, 
Len(@StringResult) - @SeperateIndex + 1))

Select @Result, @ErrorCode

在此示例中,结果如下所示:

50  -1100

只是一个想法。

【讨论】:

  • 我们正在编写一个包装器,我们实际上并不关心错误代码,因此它会比您的解决方案更简单。尽管如此,感谢您的帮助!
猜你喜欢
  • 2012-05-23
  • 2018-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多