Requery () терпит неудачу после > 1000 раз
Мне нужна помощь! Я программирую на C++ с помощью MFC и использую класс CRecordset.
Моя проблема в том, что я использую функцию Requery() примерно 10 раз в секунду во время интенсивного использования. Примерно через час такого интенсивного использования функция Requery() перестает работать; все предыдущие повторные запросы, которые работали, больше не работают! Примерно через 15 минут после этой ошибки моя программа выходит из строя. Кто-нибудь слышал об этой проблеме?
Скомпилирован в winXP (32 бит) и windows7 (64 бит) с одинаковыми результатами. Эта ошибка встречается более чем на 5 компьютерах с MS Access (2003) или SQL (2005). Единственное общее-это MSVS2005
Я получил бесплатную копию MSVC2005 от Microsoft для прохождения одного из их онлайн-курсов много лет назад; это полнофункциональное стандартное издание Visual Studio 2005.
У кого-нибудь есть какие-нибудь зацепки?
У меня есть 4 потока, обращающихся к одной функции (проблемной функции), где она направляется вниз к общему ресурсу-базе данных. Я использую семафор, чтобы запрос "только для чтения" использовался один раз. Одно из полей-это CLongBinary, где он содержит информацию об одном изображении, которая будет отображаться на экране при повторном запросе.
извините за некоторые из приведенных ниже форматов, вставьте, но вышло по-другому и вручную отредактируйте, чтобы сделать его читабельным; надеюсь
Ниже приведены некоторые фрагменты кода.
ViewClass.cpp
ПОВТОРНЫЙ ЗАПРОС:
if(m_pCardSet->IsOpen()) { m_pCardSet->m_MyParam = 1; m_pCardSet->m_nParams = 1; m_pCardSet->m_strCardNoParam = CardNo; m_pCardSet->m_strFilter = "CardNo = ?"; m_pCardSet->Requery(); if(m_pCardSet->IsEOF() && m_pCardSet->IsBOF()) { p = CardDBQue.RemoveHead(); n = InterlockedDecrement(&CardDBCount); return(_T("NO ENTRIES IN CARDHOLDER DATABASE")); }//ONLY ONE RECORD WILL SHOW, NO DUPLICATES if( (int)m_pCardSet->m_Image.m_dwDataLength < 100 ) HAS_PIX = FALSE; else HAS_PIX = TRUE; if(HAS_PIX == TRUE) if(CreateStreamOnHGlobal(NULL, TRUE, &pStream) == S_OK) { LPVOID buffer = GlobalLock(m_pCardSet->m_Image.m_hData); pStream->Write(buffer, (UINT)m_pCardSet->m_Image.m_dwDataLength, ulWritten); GlobalUnlock(m_pCardSet->m_Image.m_hData); }
..... прием.
Класс m_pCardSet: (стандартная настройка)
class CCardHolderSet : public CRecordset { public: CCardHolderSet(CDatabase* pDatabase = NULL); DECLARE_DYNAMIC(CCardHolderSet) CDBpwd m_dbParam; CStringA m_CardNo; //Card number 10 digits BOOL m_AntiPass; //is APB ACTIVE? CStringA m_FirstName; //CardHolder name (first) CStringA m_LastName; //CardHolder last name CStringA m_TransCode; //not sure CLongBinary m_Image; //picture of cardholder CStringA m_ImageName; //picture name BOOL m_Voided; //voided cards CStringA m_SecLevel; CStringA m_strCardNoParam; int m_MyParam; //varable to decide which params to use ////////// PARAMS BELOW,NOT FIELDS ////////////// // Overrides // Wizard generated virtual function overrides public: virtual CString GetDefaultConnect(); // Default connection string virtual CString GetDefaultSQL(); // default SQL for Recordset virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support // Implementation #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif };
РЕАЛИЗАЦИЯ КЛАССА ВЫШЕ:
CCardHolderSet::CCardHolderSet(CDatabase* pdb) : CRecordset(pdb) { m_CardNo = _T(""); m_AntiPass = 0; m_LastName = _T(""); m_FirstName = _T(""); m_TransCode = _T(""); m_ImageName = _T(""); m_Image.m_hData = 0; m_Voided = FALSE; m_SecLevel = _T(""); m_nFields = 9; m_nDefaultType = ConnectType; m_strCardNoParam = _T(""); m_MyParam = 0; m_nParams = 0; } CString CCardHolderSet::GetDefaultConnect() { CString Dsn; Dsn.Format("%s%s%s", m_dbParam.DbString,m_dbParam.DbParamStr, m_dbParam.DbLogonStr); return(Dsn); } CString CCardHolderSet::GetDefaultSQL() { if(CONNECT_SQL_DB == TRUE) return _T("[dbo].[CardHolder]"); else return _T("[CardHolder]"); } void CCardHolderSet::DoFieldExchange(CFieldExchange* pFX) { pFX->SetFieldType(CFieldExchange::outputColumn); RFX_Text(pFX, _T("[CardNo]"), m_CardNo); RFX_Bool(pFX, _T("[AntiPass]"), m_AntiPass); RFX_Text(pFX, _T("[FirstName]"), m_FirstName); RFX_Text(pFX, _T("[LastName]"), m_LastName); RFX_Text(pFX, _T("[TransCode]"), m_TransCode); RFX_Text(pFX, _T("[ImageName]"), m_ImageName);//m_PixName); RFX_LongBinary(pFX, _T("[Image]"), m_Image); RFX_Bool(pFX, _T("[Voided]"), m_Voided); RFX_Text(pFX, _T("[SecLevel]"), m_SecLevel, 63999); switch(m_MyParam) { case 1: pFX->SetFieldType(CFieldExchange::param); RFX_Text(pFX, "CardNo", m_strCardNoParam); break; default: break; } }
Крейг К.
Richard MacCutchan
Ничто в вышеприведенном не дает никакого ключа к пониманию того, что происходит, но это могут быть какие-то временные проблемы. Мой единственный комментарий заключается в том, что утверждениеif(m_pCardSet->IsEOF() && m_pCardSet->IsBOF())
выглядит неправильно, я не думаю, что оба этих условия могут быть истинными одновременно; вы, вероятно, имели в виду использовать ||
оператор.
Mehdi Gholam
ОПЕРАЦИЯ :
Привет и спасибо за ответ,
Я использую EOF && BOF большую часть времени, потому что это будет верно только в том случае, если нет результатов; пустые наборы. Если вы запросите несуществующее значение, вы обнаружите, что оно работает и только как "&&", а не " ||"
Извините за код,но эта функция-единственная, которая выполняет запрос. Другой код(ы) массивен, около 100 000 строк только для этого проекта. Использование 4 последовательных портов, 13 потоков, 22 таблиц в любой базе данных, 8 хранимых процедур, 20 классов.
Хронометраж, по одному за раз, но непрерывный при интенсивном движении. Это программа безопасности для карт-ключей / лифтов/сигнализации и т. д. Я бы очень хотел закончить этот проект, потому что он дает мне седые волосы!