2008-12-30 93 views
2

所以,我试图使用ADO.NET来传输存储在SQL Compact数据库的图像列中的文件数据。为了做到这一点,我写了一个DataReaderStream类,它需要一个数据读取器,为顺序访问打开,并将其表示为一个流,将流上的调用重定向到Read(...)以IDataReader.GetBytes(..)。 )。Hacky Sql Compact解决方法

与Stream类相比,IDataReader.GetBytes(...)的一个“奇怪”方面是GetBytes要求客户端增加一个偏移量并在每次调用时传递该偏移量。即使访问是连续的,它也会这样做,并且不可能在数据阅读器流中“向后”读取。

IDataReader的SqlCeDataReader实现通过增加一个内部计数器来实现这一点,该计数器标识返回的字节总数。如果您传入的数字小于或大于该数字,则该方法将引发InvalidOperationException。

但是,问题在于SqlCeDataReader实现中存在一个错误,导致它将内部计数器设置为错误的值。这会导致后续对我的流的Read调用抛出异常,当它们不应该出现异常时。

我发现了一些关于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数据库中获取流式数据,而无需诉诸这种可怕的代码?

回答

-1

其实,我决定通过不在数据库中存储Blob来解决问题。

这消除了问题(我可以从文件中传输数据),还修复了一些我可能遇到的Sql Compact 4 GB大小限制的问题。

1

我联系了Microsoft(通过SQL Compact Blog),他们确认了这个错误,并建议我使用OLEDB作为解决方法。所以,我会试试看看是否适合我。