inlandchris Ответов: 2

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 классов.
Хронометраж, по одному за раз, но непрерывный при интенсивном движении. Это программа безопасности для карт-ключей / лифтов/сигнализации и т. д. Я бы очень хотел закончить этот проект, потому что он дает мне седые волосы!

2 Ответов

Рейтинг:
2

inlandchris

Отбивание набора записей с помощью Requery () не сработает. Изначально я хотел, чтобы программа постоянно обновлялась в реальном времени. Обходной путь заключается в создании динамически выделяемой структуры, содержащей все поля базы данных и все строки в памяти. Добавлена еще одна таблица, которая является TRUE / FALSE если какое-либо из полей было обновлено удаленным пользователем, это изменится на TRUE, а затем вся структура будет повторно загружена в режиме реального времени, не нарушая работу запущенной программы. Это быстрее, чем Requery() (ing) базы данных каждые 10 мс, и память в настоящее время не является проблемой.
Requery () не создан для чрезмерного использования, он потерпит неудачу. Под этим я подразумеваю чрезмерное использование, запрашивая его каждые 10-50 МС в течение 24 часов в день...


Richard MacCutchan

Этому вопросу уже более 3 лет.

Рейтинг:
1

inlandchris

Привет и спасибо за ответ,
Я использую EOF && BOF большую часть времени, потому что это будет верно только в том случае, если нет результатов; пустые наборы. Если вы запросите несуществующее значение, вы обнаружите, что оно работает и только как "&&", а не " ||"
Извините за код,но эта функция-единственная, которая выполняет запрос. Другой код(ы) массивен, около 100 000 строк только для этого проекта. Использование 4 последовательных портов, 13 потоков, 22 таблиц в любой базе данных, 8 хранимых процедур, 20 классов.
Хронометраж, по одному за раз, но непрерывный при интенсивном движении. Это программа безопасности для карт-ключей / лифтов/сигнализации и т. д. Я бы очень хотел закончить этот проект, потому что он дает мне седые волосы!


Richard MacCutchan

Пожалуйста, не публикуйте ответы в качестве решений. Используйте соответствующую кнопку ответа.

Richard MacCutchan

Однако, учитывая ваши другие комментарии, я не думаю, что можно было бы догадаться, что происходит в таком большом проекте.