所以,我正在尝试使用ADO.NET来传输存储在SQL Compact数据库中的image列中的文件数据。
为此,我编写了一个DataReaderStream类,它接受一个数据读取器,为顺序访问打开,并将其表示为流,将流上的Read(...)重定向到IDataReader.GetBytes(... )。
与Stream类相比,IDataReader.GetBytes(...)的一个“怪异”方面是GetBytes要求客户端增加偏移量并在每次调用时传递它。即使访问是连续的,它也会这样做,并且不可能在数据读取器流中“向后”读取。
IDataReader的SqlCeDataReader实现通过递增一个内部计数器来强制执行此操作,该计数器标识它返回的总字节数。如果传入的数字小于或大于该数字,则该方法将抛出InvalidOperationException。
然而,问题在于SqlCeDataReader实现中存在一个错误,导致它将内部计数器设置为错误的值。这导致后续调用我的流上的Read会抛出不应该出现的异常。
我在this MSDN thread上找到了有关该错误的一些信息。
我能够想出一个令人作呕的,可怕的hacky解决方法,它基本上使用反射将类中的字段更新为正确的值。
代码如下所示:
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数据库中获取流数据而不必诉诸这些可怕的代码?
答案 0 :(得分:1)
我联系了Microsoft(通过SQL Compact博客),他们确认了这个错误,并建议我使用OLEDB作为解决方法。所以,我会尝试一下,看看这对我有用。
答案 1 :(得分:-1)
实际上,我决定通过不在数据库中存储blob来解决问题。
这消除了问题(我可以从文件中传输数据),还修复了我可能遇到的一些问题,包括Sql Compact的4 GB大小限制。