所以,我試圖使用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數據庫中獲取流式數據,而無需訴諸這種可怕的代碼?