所以,我试图使用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/

10-09 01:47