我想将一个大小为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数据提供程序中没有具有类似功能的类。在这种情况下我需要使用什么?谢谢!
答案 0 :(得分:1)
目前您基本上只有一个选项(假设您想通过.NET提供程序)。将您的应用切换到x64(如果您还没有完成)并购买足够的RAM(或制作大量交换文件)。我知道,这不是最佳解决方案。
你也可以对http://tracker.firebirdsql.org/browse/DNET-279表示爱意。然后你可以上传基本尺寸无限的文件。
答案 1 :(得分:0)
我通过在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{}
}
谢谢,求助!
答案 2 :(得分:0)
您可以编写和读取大小超过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一起使用的其他高级技术:)
问候。