Как закачать большой текст через .NET провайдеры

Привет всем.

В качестве эксперимента по закачке больших объемов данных (например — текстовых), я создал следующий забавный пример на C#, передающий в стандартный OLEDB.NET и наш LCPI.OLEDB.NET провайдеры объект с интерфейсом IIBP_ISequenialStream_WideChar.

Здесь Test_LCPI_OLEDB_NET работает с нашим .NET провайдером, а Test_STD_OLEDB_NET — со стандартным. В первом случае код получается немного более компактный и работает с именованными параметрами.

Для простоты IBP_TextStreamReader работает с объектом string. Однако его можно переделать так, чтобы он, к примеру, читал и возвращал данные из текстового файла.

using System;
using System.Data;
using System.Diagnostics;
using System.Security;
using System.Runtime.InteropServices;
using com_lib=lcpi.lib.com;
using structure_lib=lcpi.lib.structure;

using xdb=lcpi.data.oledb;
using sdb=System.Data.OleDb;

namespace ConsoleApplication1
{
 [ComVisible(true)]
 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
 [SuppressUnmanagedCodeSecurity]
 [Guid("769A128F-04BF-11D8-AE8B-00A0C907DB93")]
 public unsafe interface IIBP_ISequentialStream_WideChar
 {
  [PreserveSig]
  com_lib.HResultCode Read([In] char*    pchars,
                           [In] UIntPtr  cch,
                           [In] UIntPtr* pcchRead);

  [PreserveSig]
  com_lib.HResultCode Write([In] char*    pchars,
                            [In] UIntPtr  cch,
                            [In] UIntPtr* pcchWritten);
 };//interface IIBP_ISequentialStream_WideChar

 //-----------------------------------------------------------------------
 unsafe class IBP_TextStreamReader:IIBP_ISequentialStream_WideChar
 {
  public IBP_TextStreamReader(string text)
  {
   m_text=text;
   m_pos=0;
  }//IBP_TextStreamReader

  //----------------------------------------------------------------------
  [PreserveSig]
  public com_lib.HResultCode Read([In] char*    pchars,
                                  [In] UIntPtr  cch,
                                  [In] UIntPtr* pcchRead)
  {
   if(cch!=UIntPtr.Zero && pchars==null)
    return com_lib.HResultCode.E_INVALIDARG;

   if(pcchRead!=null)
    (*pcchRead)=UIntPtr.Zero;
  
   Debug.Assert(m_pos>=0);
   Debug.Assert(m_pos<=m_text.Length);

   lock(m_guard)
   {
    if(m_pos==m_text.Length)
     return com_lib.HResultCode.S_FALSE; //EOF

    var tail_sz=structure_lib.to_unsigned.exec(m_text.Length-m_pos);

    var ncch=System.Math.Min(structure_lib.uintptr_utils.ToNumeric(cch),
                             tail_sz);

    fixed(char* ptext=m_text)
    {
     char* psrc=ptext+m_pos;
     char* esrc=psrc+ncch;
     char* pdest=pchars;

     for(;psrc!=esrc;++pdest,++psrc)
     {
      (*pdest)=(*psrc);
     }
    }//fixed

    if(pcchRead!=null)
     (*pcchRead)=structure_lib.uintptr_utils.ToUIntPtr(ncch);

    m_pos+=(int)ncch;
   }//lock

   return com_lib.HResultCode.S_OK;
  }//Read

  //----------------------------------------------------------------------
  [PreserveSig]
  public com_lib.HResultCode Write([In] char*    pchars,
                                   [In] UIntPtr  cch,
                                   [In] UIntPtr* pcchWritten)
  {
   if(cch!=UIntPtr.Zero && pchars==null)
    return com_lib.HResultCode.E_INVALIDARG;

   if(pcchWritten!=null)
    (*pcchWritten)=UIntPtr.Zero;

   return com_lib.HResultCode.E_NOTIMPL;
  }//Write

  //----------------------------------------------------------------------
  private object m_guard=new object();

  private string m_text;
  private int    m_pos;
 };//class IBP_TextStreamReader

 class Program
 {
  const string c_cn_str
   ="provider=LCPI.IBProvider.3;"
    +"location=localhost:d:\\database\\ibp_test_fb25_d3.gdb;"
    +"user id=gamer;"
    +"password=vermut;"
    +"ctype=utf8";
  
  static void Main(string[] args)
  {
   try
   {
    Test_LCPI_OLEDB_NET();

    Console.WriteLine("");
    
    Test_STD_OLEDB_NET();
   }
   catch(Exception exc)
   {
    Console.WriteLine("ERROR: {0}",exc.Message);
   }

   Console.WriteLine("[DONE] Press Any Key");

   Console.ReadKey(false);
  }//Main

 //-----------------------------------------------------------------------
  static void Test_LCPI_OLEDB_NET()
  {
   try
   {
    Console.WriteLine("Test_LCPI_OLEDB_NET");

    using(var cn=new xdb.OleDbConnection(c_cn_str))
    {
     Console.WriteLine("Connect to database ...");
     cn.Open();
     
     Console.WriteLine("Start transaction ...");
     using(var tr=cn.BeginTransaction(IsolationLevel.RepeatableRead))
     {
      const string c_sql
       ="insert into TBL_CS__UTF8 (COL_BLOB) values(:a)\n"
        +"returning COL_BLOB into :b";
    
      using(var cmd=new xdb.OleDbCommand(c_sql,cn,tr))
      {
       Console.WriteLine("Receving a parameters from provider ...");
       cmd.Parameters.Refresh();

       cmd["a"].Value=new IBP_TextStreamReader(c_cn_str);

       Console.WriteLine("Insert record ...");
       cmd.ExecuteNonQuery();

       object out_param_value=cmd["b"].Value;

       if(out_param_value==DBNull.Value)
        throw new ApplicationException("got the NULL value!");

       if(c_cn_str!=(string)out_param_value)
        throw new ApplicationException("got the unexpected value!");

       Console.WriteLine("OK: we obtained back the our text.");
      }//using cmd

      Console.WriteLine("Commit transaction ...");
      tr.Commit();
     }//using tr
    }//using cn
   }
   catch(Exception exc)
   {
    Console.WriteLine("ERROR: {0}",exc.Message);
   }
  }//Test_LCPI_OLEDB_NET

 //-----------------------------------------------------------------------
  static void Test_STD_OLEDB_NET()
  {
   try
   {
    Console.WriteLine("Test_STD_OLEDB_NET");

    using(var cn=new sdb.OleDbConnection(c_cn_str))
    {
     Console.WriteLine("Connect to database ...");
     cn.Open();
     
     Console.WriteLine("Start transaction ...");
     using(var tr=cn.BeginTransaction(IsolationLevel.RepeatableRead))
     {
      const string c_sql
       ="insert into TBL_CS__UTF8 (COL_BLOB) values(?)\n"
        +"returning COL_BLOB into ?";
    
      using(var cmd=new sdb.OleDbCommand(c_sql,cn,tr))
      {
       cmd.Parameters.Add(new sdb.OleDbParameter("",
                                                 sdb.OleDbType.Variant,
                                                 /*size*/0,
                                                 ParameterDirection.Input,
                                                 /*isNullable*/true,
                                                 /*precision*/0,
                                                 /*scale*/0,
                                                 null,
                                                 DataRowVersion.Current,
                                                 null));

       cmd.Parameters.Add(new sdb.OleDbParameter("",
                                                 sdb.OleDbType.Variant,
                                                 /*size*/0,
                                                 ParameterDirection.Output,
                                                 /*isNullable*/true,
                                                 /*precision*/0,
                                                 /*scale*/0,
                                                 null,
                                                 DataRowVersion.Current,
                                                 null));

       cmd.Parameters[0].Value=new IBP_TextStreamReader(c_cn_str);

       Console.WriteLine("Insert record ...");
       cmd.ExecuteNonQuery();

       object out_param_value=cmd.Parameters[1].Value;

       if(out_param_value==DBNull.Value)
        throw new ApplicationException("got the NULL value!");

       if(c_cn_str!=(string)out_param_value)
        throw new ApplicationException("got the unexpected value!");

       Console.WriteLine("OK: we obtained back the our text.");
      }//using cmd

      Console.WriteLine("Commit transaction ...");
      tr.Commit();
     }//using tr
    }//using cn
   }
   catch(Exception exc)
   {
    Console.WriteLine("ERROR: {0}",exc.Message);
   }
  }//Test_STD_OLEDB_NET
 };//class Program
}//namespace ConsoleApplication1

На выходе получаем:
Вывод результатов работы примера

С одной стороны — вроде как ничего военного. А с другой — ЭТО ПОБЕДА! 🙂

Leave a Comment