第一次发帖,请善待! :-) 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);
}
即使为sqlChars编码,也只会返回4000个字符。在完全库存拉动期间,API调用可能会返回超过14MB的空间。如果我理解正确sqlChars转到varchar(max)(或nvarchar(max))... 我在这里错过了什么?在sql server 2005上为.Net 3.0编译,如果这有帮助... 安迪
答案 0 :(得分:3)
SqlChars
和SqlString
都不一定与NVARCHAR(MAX)
或NVARCHAR(4000)
相关联。在.NET中,string
为NVARCHAR(MAX)
,因此SqlChars
和SqlString
都可以映射到NVARCHAR(MAX)
和NVARCHAR(4000)
。确定它是MAX
还是4000
(或技术上1
到4000
)的唯一因素是为输入参数,返回类型或结果集列声明的数据类型在CREATE [PROCEDURE | FUNCTION | AGGREGATE]
声明中。所以,你首先需要检查那里。它明确定义为NVARCHAR(4000)
。如果你只是将它(即ALTER FUNCTION
)更改为NVARCHAR(MAX)
,它将返回所有内容。
其他一些说明:
NVARCHAR
,而非VARCHAR
。如果您使用的是Visual Studio / SSDT,则可以修饰您的方法,以提供SSDT DDL生成过程的提示,告诉它使用NVARCHAR(MAX)
。您可以通过在[SqlFunction()]
装饰器上添加以下内容来实现:
[return: SqlFacet(MaxSize = -1)]
如果您希望返回类型为NVARCHAR(250)
,则可以使用MaxSize = 250
。
在SQLCLR中以这种方式使用外部资源时,您需要非常小心。 AppDomain可以长时间保持加载状态,并由所有会话共享。因此,如果您有一个例外且没有using()
构造且没有try ... finally
,您在打开的资源上调用Dispose()
,那么您可以长时间孤立这些句柄时间。这可能导致文件锁定(如果它是文件系统操作)或可能耗尽网络套接字。您需要在错误处理和资源清理方面非常彻底!非常!我在这里有一些其他答案,附加说明,例如:SQL CLR Web Service Call: Limiting Overhead。
这意味着,由于未使用using()
构造或try...catch...finally
,在当前形式中,问题中显示的代码非常存在风险。 并且事实上,在 3 return SqlChars.Null;
语句之前返回.Close()
,你已经做了一件非常糟糕的事情。如果document.IsNull
曾返回true
,则此代码将孤立该网络连接和那些外部资源!!!!!
ServicePointManager
类中设置默认连接数。Convert.ToString({input_parameter})
。所有Sql*
类型都具有Value
属性,该属性返回预期.NET类型中的传入值。因此,您只需使用uri.Value
和username.Value
等没有理由指定此方法属性:
DataAccess = DataAccessKind.Read
如果要连接数据库并访问数据,则只指定Read
。此代码中没有SqlConnection
,因此您不需要此属性,这是性能损失。同样,您也不需要using System.Data.SqlClient;
。
VARBINARY
,覆盖每个默认的2个连接URI最大值等。请注意,虽然大多数功能都在免费版本中提供,但此特定功能仅在完整版(即付费版)中可用。