MemoryStream:System.ObjectDisposedException:无法访问已处置的对象

时间:2017-09-19 00:45:00

标签: c#

以下函数用于将字符串转换为SqlXml System.Data.SqlTypes.SqlXml )。但是,它遇到了以下运行时错误?缺少什么?

  

System.ObjectDisposedException:无法访问已处置的对象。

     

对象名称:'无法尝试在关闭流时调用Read。'。

System.Data.SqlTypes.SqlXml GetXml(string s)
{
    using (var memoryStream = new MemoryStream())
    {
        var settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        settings.ConformanceLevel = ConformanceLevel.Fragment;

        using (var xmlWriter = XmlWriter.Create(memoryStream, settings))
        {
            xmlWriter.WriteString(s);
            return new SqlXml(memoryStream);
        }
    }
}

错误发生在最后一行。

var range = GetXml("<Range><Column Name=\"Id\" Low=\"3397\" High=\"8999\" /></Range>");
cmd.Parameters.Add(new SqlParameter("@range", SqlDbType.Xml) { Value = range });
var result = cmd.ExecuteScalar();

2 个答案:

答案 0 :(得分:2)

如果没有良好的Minimal, Complete, and Verifiable code example,特别是有关SqlZml课程的详细信息,则无法完美地诊断您的问题。但...

您正在处置memoryStream。似乎SqlXml构造函数不会立即读取流,而是等到您尝试实际使用SqlXml对象。由于您已经处理了传递给memoryStream构造函数的SqlXml对象,因此当SqlXml尝试从该流中读取时会出现异常。

在不知道SqlXml是什么或者它应该如何工作的情况下,我无法确定正确处理这个问题的方法是什么。但是,您很可能只需要停止处置memoryStream对象。即不包含using声明。无论如何都不需要处理MemoryStream对象(它不包含任何非托管资源),并且假设SqlXml被正确写入,它将拥有Stream个对象的所有权传递给它。因此,您需要做的就是记住稍后在完成它时处置SqlXml对象。

如果上述问题无法解决您的疑虑,请通过提供更多详细信息来改进问题,包括良好的MCVE以及SqlXml课程的具体内容及其运作方式。

答案 1 :(得分:0)

在您发布的示例中,SqlXml对象将memoryStream实例作为依赖项使用,并在新SqlXml对象的范围内保存对它的引用,但它不会在代码到达GetXml()方法的return语句之前,不要对它做任何事情。

using (var memoryStream = new MemoryStream())返回时,GetXml()块已完成,因此运行时会释放memoryStream实例。之后,SqlXml对象包含对已处置对象的引用,并且尝试在SqlXml对象中使用该引用会导致您遇到异常。

解决方案可能是使SqlXml对象实现IDisposable,因此当在该对象上调用Dispose()时,它会释放MemoryStream本身。然后,您可以将调用包裹在GetXml()块中的using

using (SqlXml range = GetXml("...")) 
{
    ...
}