CLR 函数不会 return 超过 4000 个字符
CLR function will not return more than 4000 chars
第一次发帖,请多多包涵! :-)
VB/C# 的新手,尝试修复调用 Web 服务的 CLR 函数。我拼凑了以下内容:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Collections;
using System.Globalization;
// For the SQL Server integration
using Microsoft.SqlServer.Server;
// Other things we need for WebRequest
using System.Net;
using System.Text;
using System.IO;
public partial class UserDefinedFunctions
{
// Function to return a web URL as a string value.
[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
public static SqlChars GET(SqlString uri, SqlString username, SqlString passwd)
{
// The SqlPipe is how we send data back to the caller
SqlPipe pipe = SqlContext.Pipe;
SqlChars document;
// Set up the request, including authentication
WebRequest req = WebRequest.Create(Convert.ToString(uri));
if (Convert.ToString(username) != null & Convert.ToString(username) != "")
{
req.Credentials = new NetworkCredential(
Convert.ToString(username),
Convert.ToString(passwd));
}
((HttpWebRequest)req).UserAgent = "CLR web client on SQL Server";
// Fire off the request and retrieve the response.
// We'll put the response in the string variable "document".
WebResponse resp = req.GetResponse();
Stream dataStream = resp.GetResponseStream();
StreamReader rdr = new StreamReader(dataStream);
document = new SqlChars(rdr.ReadToEnd());
if (document.IsNull)
{
return SqlChars.Null;
}
// Close up everything...
rdr.Close();
dataStream.Close();
resp.Close();
// .. and return the output to the caller.
return (document);
}
这将只有 return 4000 个字符,即使它被编码为 sql 个字符。 API 调用可能会 return 在整个库存提取期间超过 14MB。如果我理解正确 sqlChars 转到 varchar(max)(或 nvarchar(max))...
我在这里错过了什么?在 sql 服务器 2005 上为 .Net 3.0 编译,如果有帮助...
安迪
SqlChars
和 SqlString
都不一定绑定到 NVARCHAR(MAX)
或 NVARCHAR(4000)
。在 .NET 中,string
是 NVARCHAR(MAX)
,因此 SqlChars
和 SqlString
都可以映射到 NVARCHAR(MAX)
和 NVARCHAR(4000)
。唯一决定它是 MAX
还是 4000
(或技术上 1
到 4000
)的是为输入参数声明的数据类型,return 类型,或 CREATE [PROCEDURE | FUNCTION | AGGREGATE]
语句中的结果集列。所以,你首先需要检查那里。明确定义为NVARCHAR(4000)
。如果您只是将它(即 ALTER FUNCTION
)更改为 NVARCHAR(MAX)
,它将 return 一切。
一些其他注意事项:
- SQLCLR API 只允许
NVARCHAR
,而不是 VARCHAR
。
如果您正在使用 Visual Studio / SSDT,您可以修饰您的方法,为 SSDT DDL 生成过程提供提示,告诉它使用 NVARCHAR(MAX)
。您可以通过在 [SqlFunction()]
装饰器上方添加以下内容来做到这一点:
[return: SqlFacet(MaxSize = -1)]
如果您希望 return 类型为 NVARCHAR(250)
,您可以使用 MaxSize = 250
.
在 SQLCLR 中以这种方式使用外部资源时,您需要非常小心。 AppDomain 可以长时间保持加载状态,并由所有 Session 共享。因此,如果您遇到异常并且没有 using()
构造并且没有 try ... finally
在其中您在打开的资源上调用 Dispose()
,那么您可以长时间孤立这些句柄时间。这可能会导致文件锁定(如果它是文件系统操作)或可能会用完网络套接字。您需要非常彻底处理此处的错误处理和资源清理!非常!我在这里有一些其他的答案和附加注释,例如:SQL CLR Web Service Call: Limiting Overhead.
这意味着,在当前形式下,问题中显示的代码 非常 有风险,因为既不使用 using()
构造也不使用 try...catch...finally
. 事实上,在 3 个 .Close()
语句之前 returning return SqlChars.Null;
,你已经做了一件非常糟糕的事情。如果 document.IsNull
曾 returns true
,那么此代码将孤立该网络连接和那些外部资源!!!!
- 如果这个 UDF 一次只被一个 session / 进程调用,并且永远不会被多个进程调用,那么你没问题。否则,您将 运行 进入默认外部连接数为 2 的问题,该问题会导致其他连接等待直到两个允许的连接之一关闭。在这种情况下,您需要在
ServicePointManager
class. 中设置默认连接数
- 没有理由像您那样调用
Convert.ToString({input_parameter})
。所有 Sql*
类型都有一个 Value
属性,它 return 是预期 .NET 类型中传入的值。因此,您可以简单地使用 uri.Value
和 username.Value
等
没有理由指定此方法属性 属性:
DataAccess = DataAccessKind.Read
如果您要连接到数据库并访问数据,则只需指定 Read
。此代码中没有 SqlConnection
,因此您不需要此 属性,这会影响性能。同样,您也不需要 using System.Data.SqlClient;
.
- 有关使用 SQLCLR 的更多信息,请参阅我在 SQLCLR Info
上发布的资源列表
- 对于任何对 WebRequest SQLCLR UDF 的全功能 pre-done 实现感兴趣的人,这样的函数已经存在于 SQL# 库(我编写的)中。该函数名为 INET_GetWebPages 并支持传入所有(或至少大部分)HTTP headers 包括自定义 headers,发送 POST数据,以
VARBINARY
形式返回二进制数据,覆盖默认的每个 URI 最多 2 个连接等。请注意,虽然大多数功能在免费版中可用,但此特定功能仅在完整版(即付费版)中可用版本。
第一次发帖,请多多包涵! :-) VB/C# 的新手,尝试修复调用 Web 服务的 CLR 函数。我拼凑了以下内容:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Collections;
using System.Globalization;
// For the SQL Server integration
using Microsoft.SqlServer.Server;
// Other things we need for WebRequest
using System.Net;
using System.Text;
using System.IO;
public partial class UserDefinedFunctions
{
// Function to return a web URL as a string value.
[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
public static SqlChars GET(SqlString uri, SqlString username, SqlString passwd)
{
// The SqlPipe is how we send data back to the caller
SqlPipe pipe = SqlContext.Pipe;
SqlChars document;
// Set up the request, including authentication
WebRequest req = WebRequest.Create(Convert.ToString(uri));
if (Convert.ToString(username) != null & Convert.ToString(username) != "")
{
req.Credentials = new NetworkCredential(
Convert.ToString(username),
Convert.ToString(passwd));
}
((HttpWebRequest)req).UserAgent = "CLR web client on SQL Server";
// Fire off the request and retrieve the response.
// We'll put the response in the string variable "document".
WebResponse resp = req.GetResponse();
Stream dataStream = resp.GetResponseStream();
StreamReader rdr = new StreamReader(dataStream);
document = new SqlChars(rdr.ReadToEnd());
if (document.IsNull)
{
return SqlChars.Null;
}
// Close up everything...
rdr.Close();
dataStream.Close();
resp.Close();
// .. and return the output to the caller.
return (document);
}
这将只有 return 4000 个字符,即使它被编码为 sql 个字符。 API 调用可能会 return 在整个库存提取期间超过 14MB。如果我理解正确 sqlChars 转到 varchar(max)(或 nvarchar(max))... 我在这里错过了什么?在 sql 服务器 2005 上为 .Net 3.0 编译,如果有帮助... 安迪
SqlChars
和 SqlString
都不一定绑定到 NVARCHAR(MAX)
或 NVARCHAR(4000)
。在 .NET 中,string
是 NVARCHAR(MAX)
,因此 SqlChars
和 SqlString
都可以映射到 NVARCHAR(MAX)
和 NVARCHAR(4000)
。唯一决定它是 MAX
还是 4000
(或技术上 1
到 4000
)的是为输入参数声明的数据类型,return 类型,或 CREATE [PROCEDURE | FUNCTION | AGGREGATE]
语句中的结果集列。所以,你首先需要检查那里。明确定义为NVARCHAR(4000)
。如果您只是将它(即 ALTER FUNCTION
)更改为 NVARCHAR(MAX)
,它将 return 一切。
一些其他注意事项:
- SQLCLR API 只允许
NVARCHAR
,而不是VARCHAR
。 如果您正在使用 Visual Studio / SSDT,您可以修饰您的方法,为 SSDT DDL 生成过程提供提示,告诉它使用
NVARCHAR(MAX)
。您可以通过在[SqlFunction()]
装饰器上方添加以下内容来做到这一点:[return: SqlFacet(MaxSize = -1)]
如果您希望 return 类型为
NVARCHAR(250)
,您可以使用MaxSize = 250
.在 SQLCLR 中以这种方式使用外部资源时,您需要非常小心。 AppDomain 可以长时间保持加载状态,并由所有 Session 共享。因此,如果您遇到异常并且没有
using()
构造并且没有try ... finally
在其中您在打开的资源上调用Dispose()
,那么您可以长时间孤立这些句柄时间。这可能会导致文件锁定(如果它是文件系统操作)或可能会用完网络套接字。您需要非常彻底处理此处的错误处理和资源清理!非常!我在这里有一些其他的答案和附加注释,例如:SQL CLR Web Service Call: Limiting Overhead.这意味着,在当前形式下,问题中显示的代码 非常 有风险,因为既不使用
using()
构造也不使用try...catch...finally
. 事实上,在 3 个.Close()
语句之前 returningreturn SqlChars.Null;
,你已经做了一件非常糟糕的事情。如果document.IsNull
曾 returnstrue
,那么此代码将孤立该网络连接和那些外部资源!!!!- 如果这个 UDF 一次只被一个 session / 进程调用,并且永远不会被多个进程调用,那么你没问题。否则,您将 运行 进入默认外部连接数为 2 的问题,该问题会导致其他连接等待直到两个允许的连接之一关闭。在这种情况下,您需要在
ServicePointManager
class. 中设置默认连接数
- 没有理由像您那样调用
Convert.ToString({input_parameter})
。所有Sql*
类型都有一个Value
属性,它 return 是预期 .NET 类型中传入的值。因此,您可以简单地使用uri.Value
和username.Value
等 没有理由指定此方法属性 属性:
DataAccess = DataAccessKind.Read
如果您要连接到数据库并访问数据,则只需指定
Read
。此代码中没有SqlConnection
,因此您不需要此 属性,这会影响性能。同样,您也不需要using System.Data.SqlClient;
.- 有关使用 SQLCLR 的更多信息,请参阅我在 SQLCLR Info 上发布的资源列表
- 对于任何对 WebRequest SQLCLR UDF 的全功能 pre-done 实现感兴趣的人,这样的函数已经存在于 SQL# 库(我编写的)中。该函数名为 INET_GetWebPages 并支持传入所有(或至少大部分)HTTP headers 包括自定义 headers,发送 POST数据,以
VARBINARY
形式返回二进制数据,覆盖默认的每个 URI 最多 2 个连接等。请注意,虽然大多数功能在免费版中可用,但此特定功能仅在完整版(即付费版)中可用版本。