Дата публикации: 03.06.2013
Запись и чтение большого (8GB) бинарного блоба (C#)
//////////////////////////////////////////////////////////////////////////////// //Samples for LCPI ADO.NET Data provider for OLEDB. // 28.05.2013 using System; using System.Diagnostics; using System.Data; using lcpi.data.oledb; using com_lib=lcpi.lib.com; using oledb_lib=lcpi.lib.oledb; namespace Sample_0007{ //////////////////////////////////////////////////////////////////////////////// //class Generator static class Generator { public static byte exec(long i) { return (byte)(i%253); }//GenByte };//class Generator //////////////////////////////////////////////////////////////////////////////// //class VirtualComStream unsafe class VirtualComStream:oledb_lib.native.ISequentialStream { public VirtualComStream(long size) { Debug.Assert(size>=0); m_size=size; m_pos=0; }//VirtualComStream //ISequentialStream interface ------------------------------------------- public com_lib.HResultCode Read(void* pv, UInt32 cb, UInt32* pcbRead) { com_lib.ObjectUtils.ClearErrorInfo(); if(pv==null && cb!=0) return com_lib.HResultCode.E_INVALIDARG; if(pcbRead!=null) (*pcbRead)=0; long pos=m_pos; byte* dest_beg=(byte*)pv; byte* dest_pos=dest_beg; byte* dest_end=dest_beg+cb; for(;dest_pos!=dest_end && pos<m_size;++dest_pos,++pos) (*dest_pos)=Generator.exec(pos); m_pos=pos; var writed=(dest_pos-dest_beg); Debug.Assert(writed<=UInt32.MaxValue); if(writed==0 && m_pos==m_size) return com_lib.HResultCode.S_FALSE; if(pcbRead!=null) lcpi.lib.structure.NumericCast.Exec(out (*pcbRead),writed); //no problem return com_lib.HResultCode.S_OK; }//Read //----------------------------------------------------------------------- public com_lib.HResultCode Write(void* pv, UInt32 cb, UInt32* pcbWrited) { com_lib.ObjectUtils.ClearErrorInfo(); if(pv==null && cb!=0) return com_lib.HResultCode.E_INVALIDARG; if(pcbWrited!=null) (*pcbWrited)=0; return com_lib.HResultCode.E_NOTIMPL; }//Write //private data ---------------------------------------------------------- private readonly long m_size; private long m_pos; };//class VirtualComStream //////////////////////////////////////////////////////////////////////////////// //class Program class Program { private const string c_cn_str ="provider=LCPI.IBProvider.3;" +"location=localhost:d:\\database\\ibp_test_fb25_d3.gdb;" +"user id=gamer;" +"password=vermut;"; //---------------------------------------------------------------------- static int Main(string[] args) { int resultCode=0; try { const long c_size=8L*1024L*1024L*1024L; //8GB //--------------------------------------- var cn=new OleDbConnection(c_cn_str); cn.Open(); var tr=cn.BeginTransaction(IsolationLevel.RepeatableRead); var cmd=new OleDbCommand("",cn,tr); //--------------------------------------INSERT Console.WriteLine("Insert BLOB ... "); cmd.CommandText="insert into BIN_BLOB_TABLE (BIN_DATA) values(:x)\n" +"returning TEST_ID\n" +"into :rec_id"; //define INPUT parameter cmd["x"].Value=new VirtualComStream(c_size); cmd.ExecuteNonQuery(); var rec_id=cmd.Parameters["rec_id"].Value; Console.WriteLine("TEST_ID={0}", rec_id); //--------------------------------------SELECT OCTET_LENGTH Console.Write("Query length of our BLOB ... "); try { cmd.CommandText="select OCTET_LENGTH (BIN_DATA) from BIN_BLOB_TABLE\n" +"where test_id=:id"; cmd["id"].Value=rec_id; var length=cmd.ExecuteScalar(); if(c_size.Equals(length)) Console.Write("OK. Length: {0}",length); else Console.Write("PROBLEM. Length: {0}",length); } catch { Console.Write("FAILED!"); throw; } finally { Console.WriteLine(""); }//finally //---------------------------------------Select data Console.WriteLine("Read and check our BLOB ... "); cmd.CommandText="select BIN_DATA from BIN_BLOB_TABLE where\n" +"test_id=:id"; cmd["id"].Value=rec_id; using(var reader=cmd.ExecuteReader(CommandBehavior.SingleResult)) { if(!reader.Read()) throw new ApplicationException("test record not found!"); using(var blob_stream=reader.GetStream(0)) { const int c_block_sz=1024*1024+1; var buffer=new byte[c_block_sz]; long total_sz=0; for(;;) { var sz=blob_stream.Read(buffer,0,c_block_sz); if(sz==0) break; int i=0; for(;i<sz && total_sz<c_size;++i,++total_sz) { if(buffer[i]!=Generator.exec(total_sz)) throw new ApplicationException("Bad BLOB data!"); }//for if(i!=sz) throw new ApplicationException("Bad BLOB data!"); }//for[ever] if(total_sz!=c_size) throw new ApplicationException("Bad BLOB data!"); }//using blob_stream if(reader.Read()) throw new ApplicationException("More that one test row!"); }//using reader //--------------------------------------- //Commit transaction tr.Commit(); //----- Console.WriteLine("All is OK."); } catch(Exception e) { resultCode=1; Console.WriteLine(""); Console.WriteLine("ERROR: {0} - {1}",e.Source,e.Message); }//catch return resultCode; }//Main }//class Program //////////////////////////////////////////////////////////////////////////////// }//namespace Sample_0007