繁体   English   中英

如何使用.NET数据提供程序更新Firebird数据库中具有大文件(1Gb)的二进制Blob字段?

[英]How can I update binary blob field with large file (1Gb) in firebird db using .NET data provider?

我想将一个大小为1Gb的大文件上传到我的firebird数据库。 我不断在下面的代码中抛出“ System.OutOfMemoryException”。

FbTransaction trans = conn.BeginTransaction();
string updateSQL = string.Format( @"UPDATE {0} SET {1} = :DATA WHERE {2} RETURNING DATA", tableName, colName, whereStr );
using( FbCommand getBlobCmd = new FbCommand( updateSQL, conn ) )
{
  try
  {
    getBlobCmd.Transaction = trans;
    FbParameter parBlob = new FbParameter( "DATA", FbDbType.Binary );
    parBlob.Direction = ParameterDirection.Output;
    parBlob.Value = File.ReadAllBytes(filePath); //System.OutOfMemoryException
    getBlobCmd.Parameters.Add( parBlob );
    getBlobCmd.ExecuteNonQuery();
    trans.Commit();
  }
  catch
  {
    if( trans != null )
      trans.Rollback();
  }
}

我了解我需要分块写入数据。 但是.NET数据提供程序中没有类似功能的类。 在这种情况下我需要使用什么? 谢谢!

当前,您基本上只有一个选择(假设您想通过.NET提供程序访问)。 将您的应用切换到x64(如果尚未执行此操作),然后购买足够的RAM(或制作较大的交换文件)。 我知道这不是最佳解决方案。

您也可以对http://tracker.firebirdsql.org/browse/DNET-279表示爱。 然后,您可以上传基本上没有大小限制的文件。

我通过在BlobBase.cs中添加方法解决了该问题:

    public void Write( Stream stream )
    { 
        try
        {
            this.Create();

            byte[] tmpBuffer = null;

            int length = (int)stream.Length;
            int offset  = 0;
            int chunk   = length >= this.segmentSize ? this.segmentSize : length;

            tmpBuffer = new byte[chunk];

            while( length > 0 )
            {
                if( chunk > length )
                {
                    chunk = ( int )length;
                    tmpBuffer = new byte[ chunk ];
                }

                stream.Read( tmpBuffer, 0, chunk );
                this.PutSegment( tmpBuffer );

                offset += chunk;
                length -= chunk;
            }

            this.Close();
        }
        catch (Exception)
        {
            // Cancel the blob and rethrow the exception
            this.Cancel();

            throw;
        }
    }

和FbCommand.cs:

BlobBase blob = this.statement.CreateBlob();
if( this.Parameters[ index ].Value is System.IO.Stream )
{
  blob.Write( (System.IO.Stream)this.Parameters[ index ].Value );
}
else
{
   blob.Write( (byte[])this.Parameters[ index ].Value );
}

最后使用的代码段:

string updateSQL = string.Format( @"UPDATE {0} SET {1} = :DATA WHERE {2}",    tableName, colName, whereStr );

using( FbCommand getBlobCmd = new FbCommand( updateSQL, conn ) )
{
  try
  {
    FbParameter parBlob = new FbParameter( "DATA", FbDbType.Binary );
    parBlob.Direction = ParameterDirection.Input;
    parBlob.Value = blobFile.InnerStream;//input FileStream
    getBlobCmd.Parameters.Add( parBlob );
    getBlobCmd.Prepare();
    getBlobCmd.ExecuteNonQuery();
  }
  catch{}
}

感谢帮助!

您可以读写大小超过1GB的BLOB数据(文本和二进制):)

“ IBProvider” +“ LCPI .NET数据提供程序”对System.IO.Stream和System.IO.TextReader具有本机支持,以避免对物理内存的任何限制。

[System.IO.Stream的使用] http://www.ibprovider.com/eng/examples/lcpi_oledb_net__c001__example_0001.html

[使用System.IO.FileStream的工作示例] [俄语文本] http://firebirder.ru/firebird_interbase__and__system_io_stream__system_io_textreader

在IBProvider网站上查看其他类似的示例,并找到与Firebird BLOB一起使用的其他高级技术:)

问候。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM