![](/img/trans.png)
[英]How can I quickly create large (>1gb) text+binary files with “natural” content? (C#)
[英]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.