首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SqlBulkCopy,MySqlDataReader,BLOB和IndexOutOfRangeException

SqlBulkCopy,MySqlDataReader,BLOB和IndexOutOfRangeException
EN

Stack Overflow用户
提问于 2021-01-16 23:04:54
回答 1查看 114关注 0票数 0

所以,当我在BLOB列中使用IndexOutOfRangeException时,我会碰到臭名昭著的MySqlDataReader。不过,我的情况很具体。故事如下。我首先通过执行命令获取MySQL中的MySqlDataReader,然后将其传递给SqlBulkCopy进行“流”批量插入,从而将数据从Server中提取到Server中。代码简单明了:

代码语言:javascript
复制
    public static void BulkCopyMySqlDataReader(string destinationConnectionString, int batchSize, string destinationTableName, IEnumerable<string> sourceColumns, MySqlDataReader mySqlDataReader)
    {
        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnectionString, SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.Default))
        {
            bulkCopy.BulkCopyTimeout = 0;
            bulkCopy.BatchSize = batchSize;
            bulkCopy.DestinationTableName = destinationTableName;
            bulkCopy.EnableStreaming = true;

            foreach (var dataColumn in sourceColumns)
                _ = bulkCopy.ColumnMappings.Add(dataColumn, dataColumn);

            try
            {
                bulkCopy.WriteToServer(mySqlDataReader);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }

但是,在MySQL端,所有这些都很好,我有两个带有BLOB列的表,这里是问题的起点。加载这些表时,它会抛出:

代码语言:javascript
复制
System.IndexOutOfRangeException: Data index must be a valid index in the field
System.IndexOutOfRangeException: 
   at MySql.Data.MySqlClient.Interceptors.ExceptionInterceptor.Throw(Exception exception)
   at MySql.Data.MySqlClient.MySqlDataReader.Throw(Exception ex)
   at MySql.Data.MySqlClient.MySqlDataReader.GetBytes(Int32 i, Int64 fieldOffset, Byte[] buffer, Int32 bufferoffset, Int32 length)

因此,正如我所理解的,SqlBulkCopy自己决定必须调用GetBytes()方法来流BLOB列的数据,这就是我得到这个异常的地方。由于特定的原因,我被绑定到8.0.15版的MySql.Data库。因此,即使在较新的版本中修复了它,我也不得不自己处理。我的想法是以某种方式覆盖GetBytes()来克服这个问题。

由于MySqlDataReader是密封的,因此不可能从它继承。因此,我正在考虑使用Decorator模式,并如下所示:

代码语言:javascript
复制
public sealed class MySqlDataReaderFixed : DbDataReader, IDataReader, IDisposable, IDataRecord
{
    public MySqlDataReader mySqlDataReader { get; set; }
//override required methods like...
    public override bool GetBoolean(int ordinal)
    {
        return mySqlDataReader.GetBoolean(ordinal);
    }
}

那么,现在如何正确地执行GetBytes()呢?也就是说,在我的MySqlDataReaderFixed课程中应该有什么内容:

代码语言:javascript
复制
    public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
    {
        var bufferLength = mySqlDataReader.GetBytes(ordinal, 0, null, 0, 0);
        // what's next?
    }

这里有人能帮忙吗?或者,也许还有另一种解决问题的方法,考虑仍然使用MySqlDataReader (来自MySql.Data v8.0.15.0)和SqlBulkCopy?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-16 23:47:14

原来我以前得看上去“一步”。SqlBulkCopy实际上是在调用GetStream()方法,该方法反过来调用麻烦制造者GetBytes()。因此,我在我的装饰类中重写了GetStream(),如下所示(摘自here):

代码语言:javascript
复制
public override Stream GetStream(int ordinal)
{
    return new MemoryStream((byte[])mySqlDataReader[ordinal]);
}

然后,问题就解决了!即使性能也很好,但是,我测试过的表相对较小。稍后我将有机会在更大的卷上测试它,让我们看看。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65755643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档