Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[ADO C++] Obsluga Event'ow.( Obiekt - Connection, Event - ExecuteComplete)

Ostatnio zmodyfikowano 2013-12-11 14:24
Autor Wiadomość
berkov
Temat założony przez niniejszego użytkownika
[ADO C++] Obsluga Event'ow.( Obiekt - Connection, Event - ExecuteComplete)
» 2013-12-09 18:38:11
Hey ho..

taka sytuacja....

Z WINAPI lacze sie przez ADO do MS Access'a, w taki oto sposob:
C/C++
ADODB::_ConnectionPtr connection;
ADODB::_RecordsetPtr recordset;
HRESULT hr;

hr = CoInitialize( NULL );
if( FAILED( hr ) )
{
    MessageBox( 0, "IMS Error Handler - Blad 0202 - Brak inicjacji bibliotek COM", "Blad 0202", 0 );
}


hr = connection.CreateInstance( __uuidof( ADODB::Connection ) );
if( FAILED( hr ) )
{
    MessageBox( 0, "IMS error handler - Blad 0203 - Brak deklaracji _ConnectionPtr ADO", "Blad 0203", 0 );
}

hr = recordset.CreateInstance( __uuidof( ADODB::Recordset ) );
if( FAILED( hr ) )
{
    MessageBox( 0, "IMS error handler - Blad 0204 - Brak deklaracji _RecordsetPtr ADO", "Blad 0204", 0 );
}

try
{
    connection->CursorLocation = ADODB::adUseClient;
}
catch( _com_error blad )
{
    errorhandler( blad, "0205" );
}

try
{
    connection->Open( "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + dbpath + ";Jet OLEDB:Database Password=xxx;", "", "", ADODB::adConnectUnspecified );
}
catch( _com_error blad )
{
    errorhandler( blad, "0206" );
    CoUninitialize();
    PostQuitMessage( 0 );
}

.. i teraz zwykla petla for wpisuje spora ilosc rekordow do bazy, rekordy same w sobie nie sa duze ale jest ich sporo, zazwyczaj powyzej 100, no i nastepuja od razu po sobie:

C/C++
try
{
    for( long i = 0; i <= jakaszmienna; i++ )
    {
       
        query = "INSERT INTO PLATN ("
        "pl_data, "
        "pl_user, "
        "ko_id, "
        "pl_status, "
        "pl_rodzaj, "
        "pl_kwota, "
        "pl_oproc, "
        "pl_odsetki, "
        "pl_kolejnosc, "
        "pl_datapl, "
        "pl_reminder, "
        "pl_datazapl, "
        "pl_opis "
        ") VALUES ("
        + Przecinek2Kropka(( _bstr_t )( double ) PL->list[ i ]->pl_data ) + ",'"
        +( _bstr_t ) PL->list[ i ]->pl_user + "',"
        +( _bstr_t ) PL->list[ i ]->ko_id + ","
        +( _bstr_t ) PL->list[ i ]->pl_status + ","
        +( _bstr_t ) PL->list[ i ]->pl_rodzaj + ","
        + Przecinek2Kropka(( _bstr_t )( double ) PL->list[ i ]->pl_kwota ) + ","
        +( _bstr_t ) PL->list[ i ]->pl_oproc + ","
        + Przecinek2Kropka(( _bstr_t )( double ) PL->list[ i ]->pl_odsetki ) + ","
        +( _bstr_t ) PL->list[ i ]->pl_kolejnosc + ","
        +( _bstr_t )( int ) PL->list[ i ]->pl_datapl + ","
        +( _bstr_t )( int ) PL->list[ i ]->pl_reminder + ","
        +( _bstr_t )( int ) PL->list[ i ]->pl_datazapl + ",'"
        +( _bstr_t ) PL->list[ i ]->pl_opis + "'"
        + ")";
       
        connection->Execute( query, 0, 0 );
       
    }
   
}
catch( _com_error blad )
{
    errorhandler( blad, "0217" );
    CoUninitialize();
}


connection->Close();
CoUninitialize();


no i wlasnie w momencie connection-> Execute (query, 0,0) zaczynaja sie schody...
Wynika to z tego ze Execute nie czeka az skonczy sie wykonywac, kod poprostu leci dalej, i petla zazwyczaj wpisze od 10 do 50 rekordow i wyrzuci blad poniewaz kod wykona sie czasami szybciej niz execute zdarzy zapisac caly rekord.

Probowalem uzyc polaczenia asynchronicznego connection-> Execute (query, 0,ADODB::adAsyncExecute); ale doczytalem ze Access nie wspiera polaczen "rownoleglych" i najprawdopodobniej jedynym sposobem jest uzycie eventow. Innymi slowy chce zatrzymac moja petle for dopoki nie dostane powiadomienia "ExecuteComplete".

Problem tylko w tym ze dokumentacja MSDN na temat uzycia eventow w ADO to jakas masakra. Czuje sie jakbym czytal po chinsku.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms675794(v=vs.85).aspx
kompletnie nic z tego nie zrozumialem..


Czy ktos wie jak (albo zna strone ktora opisue jak) uzyc eventu ExecuteComplete (ale dla C++ a nie dla VB ktorego jest w cholere i jeszcze troche)?  Chodzi tylko o to zeby powstrzymac petle for dopoki Execute nie wykona sie calkowicie ...


Dzieki.
b

P-98828
DejaVu
» 2013-12-10 01:32:44
Frazy, które należy wpisać w wyszukiwarkę google:

http://stackoverflow.com​/questions/4127680​/ado-how-to-execute-query-synchronously-with-the-ability-to-cancel

http://www.codesynthesis.com​/products/odb/doc/manual.xhtml

/edit:
Zrób transakcję i problemu nie będziesz miał :)

Druga opcja: Jednym insertem zrób n-set dodań rekordów. Będzie działało wielokrotnie szybciej i teoretycznie powinieneś wówczas dostawać 0 lub wszystkie n-rekordów.
P-98869
berkov
Temat założony przez niniejszego użytkownika
» 2013-12-10 10:54:14
@DejaVu, dzieki za odpowiedz.. ten pierwszy link raczej nie byl przydatny, bo tam opisane jest tylko uzycie progress bara ale dalej nie mowi nic o tym jak poczekac do zakonczenia query, drugi link to o ODB...

Ale przyznaje ze nie wpadlem na pomysl wrzucenia tego do jednego query...  problem pojawil sie tylko w tym ze nagle moj _bstr_t string urosl do ogromnych rozmiarow i zaczal wyrzucac bledy dotycxace pamieci choc pracowalem na komputerze z 8GB ramu co dalo mi do myslenia.. spedzilem wiec kilka kolejnych godziny na debugowaniu zeby wychwycic gdzie dokladnie pojawia sie blad (nie bylo to proste bo pojawia sie raz na 100 - 1000 przyapdkow) pozatym blad ten tez nie byl zawsze taki sam, czasami error handler go wychwycil pisza ze np string query nie jest poprawny a czasami (zazwyczaj) wyrzucilo to:

xxx.exe has triggered a breakpoint

i wskazalo na plik biblioteki free.c:
C/C++
void __cdecl _free_base( void * pBlock )
{
   
    int retval = 0;
   
   
    if( pBlock == NULL )
         return;
   
    RTCCALLBACK( _RTC_Free_hook,( pBlock, 0 ) );
   
    retval = HeapFree( _crtheap, 0, pBlock ); //KURSUS wskazywal to miejsce
    if( retval == 0 )
    {
        errno = _get_errno_from_oserr( GetLastError() );
    }
}


lub biblioteka malloc.c:
C/C++
__forceinline void * __cdecl _heap_alloc( size_t size )

{
   
    if( _crtheap == 0 ) {
        _FF_MSGBANNER(); /* write run-time error banner */
       
        _NMSG_WRITE( _RT_CRT_NOTINIT ); /* write message */
        __crtExitProcess( 255 ); /* normally _exit(255) */
    }
   
    return HeapAlloc( _crtheap, 0, size ? size: 1 );
} //KURSUS wskazywal to miejsce


najdziwniejsze jest to ze jak program puscielem normalnie z pod windowsa (nie z pod kompilatora) to zawsze wszystko jest ok i query sie konczylo bez problemu, nawet jak poscilem za soba 1000 razy kazdy rekord z osobna (moj pierwotny kod)... wszystko dzialala cacy....

wychwycilem ze problem wyrzuca zazwyczaj w mojej funkcji Przecinek2Kropka, ktora wyglada tak:
C/C++
_bstr_t Przecinek2Kropka( _bstr_t source )
{
    char * temp = new char[ 50 ];
    temp = _com_util::ConvertBSTRToString( source );
    for( int i = 0; i < 50; i = i + 1 )
    {
        if( temp[ i ] == ',' )
        {
            temp[ i ] = '.';
        }
       
    }
    _bstr_t wynik = temp;
    delete[] temp;
    return wynik;
}


okazalo sie ze wystarzylo wykomentowac if (temp[i] == ',') (...) i program zaczal dzialac bez problemu nawet uruchomiony z pod kompilatora (MS VS Express 2010)...
oczywiscie ten if tam musi byc.. wiec teaz pytanie brzmi dlaczego moj IF nie dziala i dlaczego tylko jak program uruchomiony jest z pod kompilatora?

dzieki
b


p.s.
gdyby ktos dalej wiedzial jak uzyc eventow to bede wdzieczny, mysle ze moga sie przydac na przyszlosc...




P-98879
DejaVu
» 2013-12-10 12:26:09
Może nie masz zakończonego łańcucha znaków znakiem terminalnym?
P-98883
berkov
Temat założony przez niniejszego użytkownika
» 2013-12-10 12:27:00
Juz wiem..

ConvertBSTRToString skraca moj string dodajac na koncu \0

wiec siegajac do tablicy poza \0 powoduje blad...
Kompilator tego pilnuje ale zwykly runtime pod windowsem dopoki nie chce dostepu do czegos poza moim program co jest akurat zajete przez inny program nie sposowuje wyjatku i bledu....

kod powinien wygaldac tak:

C/C++
_bstr_t Przecinek2Kropka( _bstr_t source )
{
    int dl = source.length();
    char * temp = new char[ dl + 1 ];
    temp = _com_util::ConvertBSTRToString( source );
    for( int i = 0; i <= dl; i = i + 1 )
    {
        if( temp[ i ] == ',' )
        {
            temp[ i ] = '.';
        }
       
    }
    _bstr_t wynik = temp;
    delete[] temp;
    return wynik;
}
P-98884
berkov
Temat założony przez niniejszego użytkownika
» 2013-12-10 12:36:57
No nic.. wracajac do temuatu Events w ADO.. gdyby ktos mial zrozumiale dla przecietnego zjadacza chleba informacje "jak i z czym" to z gory dziekuje. Problem sam w sobie chociaz nie dotyczyl glownego watku jak poczatkowo myslalem jest rozwiazany.
dzieki
P-98887
Monika90
» 2013-12-10 16:48:39
C/C++
char * temp = new char[ dl + 1 ];
temp = _com_util::ConvertBSTRToString( source );
To się nazywa memory leak
P-98900
berkov
Temat założony przez niniejszego użytkownika
» 2013-12-10 19:29:34
czemu?
P-98924
« 1 » 2
  Strona 1 z 2 Następna strona