为什么得到 "Cannot read from a closed TextReader"

why get "Cannot read from a closed TextReader"

我有一个 SQL CLR 函数 return 来自 Web Json 的 Api,这是我的代码

[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,我的代码看起来不一样 有人可以帮助我。我在应用程序 cosole 中尝试了这段代码,将结果写入文件并完美运行

很难说清楚,因为您已将当前代码与 commented-out/删除的代码分开。但是一般的概念是用ReadToEnd变成一个字符串到return这个字符串才是正确的做法。

如果您不希望这段代码破坏您的 SQL 服务器,您绝对需要做的一件事就是妥善处理所有一次性物品。您应该使用 using() 构造,因为它们将包含正确的 try...finally 结构,以确保无论在嵌套集合中的哪个位置发生异常,所有资源都得到正确处理。

现在,从 ILspy 获取的图像中显示的代码显示了直接的问题,因为它正在 returning readStream.ReadToEnd()。一旦将代码放入正确的 using 结构中,并在中间执行 document = (SqlString)readStream.ReadToEnd(),那么这将按预期工作。

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。仍然出现 Cannot read from a closed TextReader 错误。
  • O.P。提到 Web 服务 return 的响应大约为 8 MB。
  • 使用上面的代码,我顺利下载了一个 11.6 MB 的文件。
  • 使用上面的代码,O.P。能够成功地从 https://jsonplaceholder.typicode.com/没问题。
  • 问题是 不是 return 数据类型的映射,因为它映射到 NVARCHAR(4000) 而不是 NVARCHAR(MAX)将导致以下错误:

    Msg 6522, Level 16, State 1, Line 2
    A .NET Framework error occurred during execution of user-defined routine or aggregate "xxxxxx":
    System.Data.SqlServer.TruncationException: Trying to convert return value or output parameter of size 24233896 bytes to a T-SQL type with a smaller size limit of 8000 bytes.
    System.Data.SqlServer.TruncationException:
          at System.Data.SqlServer.Internal.CXVariantBase.StringToWSTR(String pstrValue, Int64 cbMaxLength, Int32 iOffset, EPadding ePad)