Witam!
Prubuję napisać program, który będzie potrafił zapisywać i pobierać z bazy MS SQL obraz (typ image). Jadnek przy próbie połączenia, wyskakuje błąd "Nieprawidłowy indeks deskryptora". A więc po kolei...
Najpierw napiasłem program, który operuje na typach liczbowych, tekstowych i daty. Robiłem to za pomocą kreatora: Project -> Add Class... -> MFC -> MFC ODBC Consumer. W kreatorze trzeba bylo wskazać źródło danych ODBC (takie samo okienko jak w Panel Sterowania -> Narzędzia Administarcyjne -> Źródła danych (ODBC)). Utworzona została klasa, dziedzicząca z klasy CRecordset, która posiadała pola i nazwę takie jak tabela w bazie danych.
long m_ID; // w pliku .h klasy dziedziczącej z CRecordset
CStringW m_Imie;
CStringW m_Nazwisko;
CStringW m_Miejscowosc;
CTime m_Data_dodania;
CTime m_Data_rozpoznania;
BYTE m_Palec;
COsoby::COsoby(CDatabase* pdb) // w pliku .cpp klasy dziedziczącej z CRecordset
: CRecordset(pdb)
{
m_ID = 0;
m_Imie = L"";
m_Nazwisko = L"";
m_Miejscowosc = L"";
m_Data_dodania;
m_Data_rozpoznania;
m_Palec = 0;
m_Obraz;
m_nFields = 7;
m_nDefaultType = dynaset;
}
void COsoby::DoFieldExchange(CFieldExchange* pFX) // w pliku .cpp klasy dziedziczącej z CRecordset
{
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Long(pFX, _T("[ID]"), m_ID);
RFX_Text(pFX, _T("[Imie]"), m_Imie);
RFX_Text(pFX, _T("[Nazwisko]"), m_Nazwisko);
RFX_Text(pFX, _T("[Miejscowosc]"), m_Miejscowosc);
RFX_Date(pFX, _T("[Data_dodania]"), m_Data_dodania);
RFX_Date(pFX, _T("[Data_rozpoznania]"), m_Data_rozpoznania);
RFX_Byte(pFX, _T("[Palec]"), m_Palec);
}
Wszystko działało jak należy - program się łączył i pobierał wszystkie dane oraz mógł na tabeli w bazie operować. Jendak, gdy chiałem program poszerzyć o obsługę wczytywania i zapisywania obrazu do bazy, zaczął pojawiać się błąd w momecie jego uruchamiania:
Nieprawidłowy indeks deskryptora
Wygląd nowej klasy jest bardzo podobny, z ty, ze pojawiły się wpisy dotyczące pola image:
CLongBinary m_Obraz; // w pliku .h klasy dziedziczącej z CRecordset
[...]
m_Obraz; //w pliku .cpp klasy dziedziczącej z CRecordset
m_nFields = 8;
[...]
RFX_LongBinary(pFX, _T("[Obraz]"), m_Obraz);
Program kompiluje się bezbłędnie, jednak nie da się go uruchomić. Literówka nie jest możliwa, ponieważ tę klase kompilator tworzy sam, na podstawie Tabeli w bazie danych. Co więcej, gdy odkomentuję te pola, a m_nFields zmienię na 7, wszystko znów działa. Komunikat z błędem pojawia się
Komunikat z błędem pojawia się, gdy tworzony jest obiekt klasy, która dziedziczy z CRecordset. Chyba w miejscu RFX_LongBinary(pFX, _T("[Obraz]"), m_Obraz);. Próbowałem bawić się z typami, okazało się, że wszystkie typy jakie mam do dyspozycji to:
/////////////////////////////////////////////////////////////////////////////
// Standard Recordset Field Exchange routines
// text data
void AFXAPI RFX_Text(CFieldExchange* pFX, LPCTSTR szName, CStringW &value,
// Default max length for char and varchar, default datasource type
int nMaxLength = 255, int nColumnType = SQL_VARCHAR, short nScale = 0);
void AFXAPI RFX_Text(CFieldExchange* pFX, LPCTSTR szName, CStringA &value,
// Default max length for char and varchar, default datasource type
int nMaxLength = 255, int nColumnType = SQL_VARCHAR, short nScale = 0);
void AFXAPI RFX_Text(__in CFieldExchange* pFX, __in_z LPCTSTR szName, __out_ecount(nMaxLength) __out_z LPWSTR value,
__in int nMaxLength, __in int nColumnType = SQL_VARCHAR, __in short nScale = 0);
void AFXAPI RFX_Text(__in CFieldExchange* pFX, __in LPCTSTR szName, __out_ecount(nMaxLength) __out_z LPSTR value,
__in int nMaxLength, __in int nColumnType = SQL_VARCHAR, __in short nScale = 0);
// boolean data
void AFXAPI RFX_Bool(CFieldExchange* pFX, LPCTSTR szName, BOOL& value);
// integer data
void AFXAPI RFX_Long(CFieldExchange* pFX, LPCTSTR szName, long& value);
void AFXAPI RFX_Int(CFieldExchange* pFX, LPCTSTR szName, int& value);
void AFXAPI RFX_Single(CFieldExchange* pFX, LPCTSTR szName, float& value);
void AFXAPI RFX_Double(CFieldExchange* pFX, LPCTSTR szName, double& value);
void AFXAPI RFX_BigInt(CFieldExchange* pFX, LPCTSTR szName, LONGLONG& value);
// date and time
void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, CTime& value);
void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, TIMESTAMP_STRUCT& value);
void AFXAPI RFX_Date(CFieldExchange* pFX, LPCTSTR szName, COleDateTime& value);
// Binary data
void AFXAPI RFX_Binary(CFieldExchange* pFX, LPCTSTR szName, CByteArray& value,
// Default max length is for binary and varbinary
INT_PTR nMaxLength = 255);
void AFXAPI RFX_Byte(CFieldExchange* pFX, LPCTSTR szName, BYTE& value);
void AFXAPI RFX_LongBinary(CFieldExchange* pFX, LPCTSTR szName, CLongBinary& value);
/////////////////////////////////////////////////////////////////////////////
Dla jasności powiem, że uzywam VC++ w wersji 8 (2005), używam klas MFC, system Widnows XP.
Proszę o pomoc i cierpliwość :)