以下函数用于将字符串转换为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();
答案 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("..."))
{
...
}