SQL CLR 问题:CREATE PROCEDURE 失败,因为参数计数不匹配
SQL CLR issue: CREATE PROCEDURE failed because parameter counts do not match
我确实检查了 this,但问题似乎不是类型不匹配。
我正在尝试使用 CLR 从 blob 数据转换回文件。下面是c#代码转换为dll并使用汇编存储。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlTypes;
using System.IO;
using Microsoft.SqlServer.Server;
namespace CLRProcedures
{
public class WriteFile
{
[SqlFunction]
public static SqlInt32 WriteToFile(SqlBytes binary, SqlString path, SqlBoolean append)
{
try
{
if (!binary.IsNull && !path.IsNull && !append.IsNull)
{
var dir = Path.GetDirectoryName(path.Value);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
using (var fs = new FileStream(path.Value, append ? FileMode.Append : FileMode.OpenOrCreate))
{
byte[] byteArr = binary.Value;
for (int i = 0; i < byteArr.Length; i++)
{
fs.WriteByte(byteArr[i]);
};
}
return 1;
}
else
return 0;
}
catch (Exception ex)
{
return -2;
}
}
}
}
SQL 查询如下:
CREATE ASSEMBLY FileOutput from 'c:\dlls\CLRProcedures.dll' WITH PERMISSION_SET = SAFE
CREATE PROCEDURE FileOutput
@file varbinary(max),
@filepath nvarchar(4000),
@append bit,
@message int OUTPUT
AS
EXTERNAL NAME FileOutput.[CLRProcedures.WriteFile].WriteToFile
这会引发错误:'CREATE PROCEDURE failed because parameter counts do not match.'
我已经从 here 重新验证了是否存在类型不匹配但没有。我哪里会出错?我试图更改 return 类型的 c# 代码但同样的问题。
谢谢
您需要将 WriteToFile
函数的 OUTPUT 参数添加到 return 值
[SqlFunction]
public static void WriteToFile(SqlBytes binary, SqlString path, SqlBoolean append,out SqlInt32 message)
{
try
{
if (!binary.IsNull && !path.IsNull && !append.IsNull)
{
var dir = Path.GetDirectoryName(path.Value);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
using (var fs = new FileStream(path.Value, append ? FileMode.Append : FileMode.OpenOrCreate))
{
byte[] byteArr = binary.Value;
for (int i = 0; i < byteArr.Length; i++)
{
fs.WriteByte(byteArr[i]);
};
}
message = 1;
}
else
message = 0;
}
catch (Exception ex)
{
message = -2;
}
}
您忽略了错误消息的内容:
CREATE PROCEDURE failed because parameter counts do not match (emphasis added)
问题是参数“count”,而不是任何特定参数“type”。您在方法签名中有 3 个输入参数,但在 CREATE PROCEDURE
语句中指定了 4 个参数。
您的选择是:
- 按照 Naji 的建议添加第四个参数,在 C# 代码中声明为
out
,并将 return
更改为设置 message
变量,这将匹配您已定义 4 个参数。
- 或者,您可以保持 C# 代码不变,并以与常规 T-SQL 存储过程 return 值相同的方式获取 return 值:
DECLARE @ReturnValue INT;
EXEC @ReturnValue = dbo.FileOutput 0x1234, N'path', 1;
SELECT @ReturnValue;
- 或者,您甚至可以通过简单地将 T-SQL
CREATE
对象语句更改为:
CREATE FUNCTION dbo.FileOutput
(
@File VARBINARY(MAX),
@FilePath NVARCHAR(4000),
@Append BIT
)
RETURNS INT
AS EXTERNAL NAME ...
并按如下方式使用:
DECLARE @ReturnValue INT;
SET @ReturnValue = dbo.FileOutput(0x1234, N'path', 1);
SELECT @ReturnValue;
(从技术上讲,作为 return 是 INT
/ Int32
的标量函数,您甚至可以使用上面选项 2 中所示的相同存储过程语法来执行它)
另外:
- 如果您正在创建一个过程,您应该使用
SqlProcedure
而不是 SqlFunction
. 修饰 C# WriteToFile
方法
-
SqlBytes
类型提供了一个 Stream
属性 ,它是一个更有效的实际流,而不是将整个二进制值迭代为 byte[]
读取该值的方式。只需将 binary.Stream
复制到文件流即可完成:-)
- 始终指定模式名称(对于模式绑定对象),无论是在
CREATE
语句、SELECT
、EXEC
等中
有关使用 SQLCLR 的更多信息,请访问:SQLCLR Info
我确实检查了 this,但问题似乎不是类型不匹配。
我正在尝试使用 CLR 从 blob 数据转换回文件。下面是c#代码转换为dll并使用汇编存储。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlTypes;
using System.IO;
using Microsoft.SqlServer.Server;
namespace CLRProcedures
{
public class WriteFile
{
[SqlFunction]
public static SqlInt32 WriteToFile(SqlBytes binary, SqlString path, SqlBoolean append)
{
try
{
if (!binary.IsNull && !path.IsNull && !append.IsNull)
{
var dir = Path.GetDirectoryName(path.Value);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
using (var fs = new FileStream(path.Value, append ? FileMode.Append : FileMode.OpenOrCreate))
{
byte[] byteArr = binary.Value;
for (int i = 0; i < byteArr.Length; i++)
{
fs.WriteByte(byteArr[i]);
};
}
return 1;
}
else
return 0;
}
catch (Exception ex)
{
return -2;
}
}
}
}
SQL 查询如下:
CREATE ASSEMBLY FileOutput from 'c:\dlls\CLRProcedures.dll' WITH PERMISSION_SET = SAFE
CREATE PROCEDURE FileOutput
@file varbinary(max),
@filepath nvarchar(4000),
@append bit,
@message int OUTPUT
AS
EXTERNAL NAME FileOutput.[CLRProcedures.WriteFile].WriteToFile
这会引发错误:'CREATE PROCEDURE failed because parameter counts do not match.'
我已经从 here 重新验证了是否存在类型不匹配但没有。我哪里会出错?我试图更改 return 类型的 c# 代码但同样的问题。
谢谢
您需要将 WriteToFile
函数的 OUTPUT 参数添加到 return 值
[SqlFunction]
public static void WriteToFile(SqlBytes binary, SqlString path, SqlBoolean append,out SqlInt32 message)
{
try
{
if (!binary.IsNull && !path.IsNull && !append.IsNull)
{
var dir = Path.GetDirectoryName(path.Value);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
using (var fs = new FileStream(path.Value, append ? FileMode.Append : FileMode.OpenOrCreate))
{
byte[] byteArr = binary.Value;
for (int i = 0; i < byteArr.Length; i++)
{
fs.WriteByte(byteArr[i]);
};
}
message = 1;
}
else
message = 0;
}
catch (Exception ex)
{
message = -2;
}
}
您忽略了错误消息的内容:
CREATE PROCEDURE failed because parameter counts do not match (emphasis added)
问题是参数“count”,而不是任何特定参数“type”。您在方法签名中有 3 个输入参数,但在 CREATE PROCEDURE
语句中指定了 4 个参数。
您的选择是:
- 按照 Naji 的建议添加第四个参数,在 C# 代码中声明为
out
,并将return
更改为设置message
变量,这将匹配您已定义 4 个参数。 - 或者,您可以保持 C# 代码不变,并以与常规 T-SQL 存储过程 return 值相同的方式获取 return 值:
DECLARE @ReturnValue INT; EXEC @ReturnValue = dbo.FileOutput 0x1234, N'path', 1; SELECT @ReturnValue;
- 或者,您甚至可以通过简单地将 T-SQL
CREATE
对象语句更改为:
并按如下方式使用:CREATE FUNCTION dbo.FileOutput ( @File VARBINARY(MAX), @FilePath NVARCHAR(4000), @Append BIT ) RETURNS INT AS EXTERNAL NAME ...
(从技术上讲,作为 return 是DECLARE @ReturnValue INT; SET @ReturnValue = dbo.FileOutput(0x1234, N'path', 1); SELECT @ReturnValue;
INT
/Int32
的标量函数,您甚至可以使用上面选项 2 中所示的相同存储过程语法来执行它)
另外:
- 如果您正在创建一个过程,您应该使用
SqlProcedure
而不是SqlFunction
. 修饰 C# -
SqlBytes
类型提供了一个Stream
属性 ,它是一个更有效的实际流,而不是将整个二进制值迭代为byte[]
读取该值的方式。只需将binary.Stream
复制到文件流即可完成:-) - 始终指定模式名称(对于模式绑定对象),无论是在
CREATE
语句、SELECT
、EXEC
等中
WriteToFile
方法
有关使用 SQLCLR 的更多信息,请访问:SQLCLR Info