2008-12-30 94 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作爲解決方法。所以,我會試試看看是否適合我。