ODBC CRecordset
От: Чепель Дмитрий Михайлович Россия  
Дата: 15.11.02 10:28
Оценка:
Пишу программу с использованием ODBC CRecordet`а,
т.к. приложение критично по скорости выполнения.

OS WinXP
SQL Server: Linter v5.9
MSVC 7.0

Создаю соединение на основе класса, унаследованного от CDatabase.
Создаю рекордсет, унаследованный от CRecordset.
Переопределяю функцию DoFieldExchange,
Открываю CRecordset. Данные читаю.
Но при попытке изменить данные (метод Update), получаю exception

SQLPrepare:"ОЖидалась лексема CURSOR".

при отладке обнаружил, что для UPDATE создаётся строчка типа

UPDATE <tablename> SET <colname1>=?[,<colname2>=?] WHERE CURRENT OF <CursorName>
При этом имя курсора получается с помощью SQLGetCursorName ини циализирует один раз
переменную m_strCursorName, но эта функция
возвращает пустую строку. Я попытался после Open задать имя курсора, но ничего
не изменияется.
с помощью odbcte32.exe и odbcte32w.exe проверил, что даже без задания курсора имя
курсора возвращается для Linter.

Из доков прочитал, что возможна команда типа
UPDATE <tablename> SET <colname1>=?[,<colname2>=?] WHERE CURRENT OF CURSOR

добавил в Open строчку
m_strCursorName = "CURSOR";

Но при попытке изменить данные, получаю exception
SQLExecute: Неверная последовательность команд



00:
01:class MyDatabase:public CDatabase{
02:public:
03:    MyDatabase(const string& A,const string& U,const string& P ):CDatabase(){
04:        string Con="DSN="+A+";UID="+U+";PWD="+P+";TXN=AUTOCOMMIT;CODEPAGE=ANSI 1251;";
05:            OpenEx(Con.c_str() ,CDatabase::noOdbcDialog);
06:    }
07:    ~MyDatabase(){
08:        Close();
09:    }
10:};
11:
12:class MyRecordset:public CRecordset{
13:public:
14:    MyRecordset(const CString& T,MyDatabase& b):CRecordset(&b){
15:        CString sql = "select ID,P00,P01 from "+T+" where ver = 0;";
16:        m_nFields = 3; 
17:        int n = m_nFields-1;
18:        Fields.resize(n);
19:        Fields[0].Name = "P00";
20:        Fields[1].Name = "P01";
21:        
22:        m_nDefaultType = snapshot;
23:        Open(CRecordset::snapshot/*snapshot*/,sql,CRecordset::executeDirect);
24:        //int code=::SQLSetCursorName(  m_hstmt,reinterpret_cast<SQLTCHAR *>(_T("CR")),SQL_NTS);
25:        //m_strCursorName = "CURSOR";
26:    }
27:    ~MyRecordset(){    Close();}
28:    long m_ID;
29:    /*struct Flds{
30:        int Num;
31:        int size;
32:        CString Data;
33:        CString Name;
34:    };*/
35:    CString a;
36:    CString b;
37:    //vector<Flds> Fields;
38:    virtual void DoFieldExchange(CFieldExchange* pFX)
39:    {
40:     pFX->SetFieldType(CFieldExchange::outputColumn);
41:     RFX_Long(pFX, _T("[ID]"), m_ID);
42:     RFX_Text(pFX, _T("[P00]"), a);
43:     RFX_Text(pFX, _T("[P01]"), b);
44:     /*for(vector<Flds>::iterator ii = Fields.begin();ii!=Fields.end();++ii)
45:     {
46:         CString &name =ii->Name;
47:         CString &data =ii->Data;
48:         RFX_Text(pFX, name, data);
49:     }*/
50:    }
51:
52:};
53:
54:extern "C" void Check(const char *Alias,const char* User, const char* Pass,
55:                             const char* Table, long option){
56:            AFX_MANAGE_STATE(AfxGetStaticModuleState());
57:            MyDatabase b(Alias,User,Pass);    //OK
58:            MyRecordset r(Table,b);        //OK
59:            while(!r.IsEOF()){        //OK
60:                r.Edit();        //OK
61:                CString s=r.a;        //OK
62:                r.a = "assad";        //OK
63:                r.Update();        //Exception
64:                r.MoveNext();        //Если без Update то OK
65:            }
66:}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.