为什么得到“无法从封闭的TextReader中读取”

时间:2017-01-13 21:58:58

标签: .net sql-server sql-server-2012 sqlclr

我有一个SQL CLR函数,它从Web Api返回Json,这里是我的代码

[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString Funcion()
{
    SqlString document;
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL");
    request.Method = "GET";
    request.ContentLength = 0;
    request.Credentials = CredentialCache.DefaultCredentials;
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    Stream receiveStream = response.GetResponseStream();
    StreamReader readStream = new StreamReader(receiveStream);
    document = (SqlString)readStream.ReadToEnd();
    return document;
}

我删除下一个代码,因为我认为这是问题

     //response.Close();
    //readStream.Close();

但我仍然犯了错误

System.ObjectDisposedException: Cannot read from a closed TextReader System.ObjectDisposedException: 
at System.IO.__Error.ReaderClosed()
at System.IO.StreamReader.ReadToEnd()
at UserDefinedFunctions.Funcion()

我用ILSpy检查dll,我的代码看起来不一样 enter image description here 有人可以帮忙。我在应用程序cosole中尝试了这个代码,将结果写入文件并完美地运行

1 个答案:

答案 0 :(得分:2)

很难准确地说出您将当前代码与已注释/删除的代码分开。但是将location用于字符串以返回字符串的一般概念是正确的方法。

如果您不希望此代码丢弃您的SQL Server,您绝对需要做的一件事是正确处理所有一次性对象。您应该使用ReadToEnd构造,因为它们将包含正确的using()结构,以确保所有资源都得到正确处理,无论它们在嵌套集中的哪个位置发生异常。

现在,从ILspy中获取的图像中显示的代码显示了它正在返回try...finally的直接问题。将代码放入正确的readStream.ReadToEnd()构造中,并在中间执行using后,这将按预期工作。

document = (SqlString)readStream.ReadToEnd()

<强>更新

  • 使用上面的代码,O.P。仍然会出现string document; HttpWebRequest request = (HttpWebRequest)WebRequest.Create("URL"); request.Method = "GET"; request.ContentLength = 0; request.UseDefaultCredentials = true; // don't use CredentialCache.DefaultCredentials; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream receiveStream = response.GetResponseStream()) { using (StreamReader readStream = new StreamReader(receiveStream)) { document = readStream.ReadToEnd(); } } } return new SqlString(document); 错误。
  • O.P。提到Web服务返回大约8 MB的响应。
  • 使用上面的代码,我下载了一个11.6 MB的文件没有问题。
  • 通过上面的代码,O.P。能够成功检索到的响应 https://jsonplaceholder.typicode.com/没有问题。
  • 问题是返回数据类型的映射,因为将其映射到Cannot read from a closed TextReader而不是NVARCHAR(4000)会导致以下错误:

      

    Ms 6522,Level 16,State 1,Line 2
      在执行用户定义的例程或聚合“xxxxxx”期间发生.NET Framework错误:
      System.Data.SqlServer.TruncationException:尝试将大小为24233896字节的返回值或输出参数转换为大小限制为8000字节的T-SQL类型。
      System.Data.SqlServer.TruncationException:
      在System.Data.SqlServer.Internal.CXVariantBase.StringToWSTR(String pstrValue,Int64 cbMaxLength,Int32 iOffset,EPadding ePad)