所以,我试图使用ado.net来传输存储在sql compact数据库的图像列中的文件数据。
为此,我编写了一个data reader stream类,该类接受一个数据读取器,为顺序访问打开,并将其表示为流,将流上的read(…)调用重定向到i data reader.getbytes(…)。
与stream类相比,idatareader.getbytes(…)的一个“奇怪”方面是getbytes要求客户端增加偏移量,并在每次调用时传递偏移量。即使访问是连续的,也不可能在数据读取器流中“向后”读取。
idatareader的sqlcedatareader实现通过递增一个内部计数器来实现这一点,该计数器标识它返回的字节总数。如果传入的数字小于或大于该数字,则该方法将引发InvalidOperationException。
但是,问题是sqlcedatareader实现中存在一个错误,导致它将内部计数器设置为错误的值。这会导致随后的读取流调用在不应该发生异常时抛出异常。
我在this MSDN thread上找到了一些关于这个bug的信息。
我想出了一个恶心的、骇人听闻的解决方法,它基本上使用反射将类中的字段更新为正确的值。
代码如下所示:
public override int Read(byte[] buffer, int offset, int count)
{
m_length = m_length ?? m_dr.GetBytes(0, 0, null, offset, count);
if (m_fieldOffSet < m_length)
{
var bytesRead = m_dr.GetBytes(0, m_fieldOffSet, buffer, offset, count);
m_fieldOffSet += bytesRead;
if (m_dr is SqlCeDataReader)
{
//BEGIN HACK
//This is a horrible HACK.
m_field = m_field ?? typeof (SqlCeDataReader).GetField("sequentialUnitsRead", BindingFlags.NonPublic | BindingFlags.Instance);
var length = (long)(m_field.GetValue(m_dr));
if (length != m_fieldOffSet)
{
m_field.SetValue(m_dr, m_fieldOffSet);
}
//END HACK
}
return (int) bytesRead;
}
else
{
return 0;
}
}
显然,我不想用这个。
但是,我也不想在内存中缓冲blob的全部内容。
有谁知道我可以不必使用如此糟糕的代码就可以从sql compact数据库中获取流式数据吗?
最佳答案
我联系了微软(通过sql compact博客),他们确认了这个错误,并建议我使用oledb作为解决方法。所以,我会试试看这对我是否有效。
关于sql - Hacky Sql Compact解决方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/399719/