Click here to Skip to main content
15,896,471 members
Articles / Desktop Programming / MFC

Command Pattern at Work in a Database Application

Rate me:
Please Sign up or sign in to vote.
4.70/5 (16 votes)
8 Feb 2011CPOL6 min read 38.2K   457   36  
A practical example of command pattern applied in a database application
#include "StdAfx.h"
#include "GDataBaseCommand.h"
#include "DataGrid.h"

#include "Resource.h"

struct BookMarkVsCommand
{
	CGDataBaseCommand* pCmd;
	_variant_t vBookMark;

	BookMarkVsCommand()
	{
		vBookMark.vt = VT_EMPTY;
		pCmd = NULL;
	}
};
CArray<BookMarkVsCommand, BookMarkVsCommand&> m_mapBookMarksVsCommands;

void SetCommandInfoAt(CGDataBaseCommand* pCmd, _variant_t vBookMark)
{
	// check if add command exists 
	for(int i = m_mapBookMarksVsCommands.GetSize() - 1; i >=0 ; i--)
	{
		if(m_mapBookMarksVsCommands[i].pCmd == pCmd)
		{
			m_mapBookMarksVsCommands[i].vBookMark = vBookMark;
			return;
		}
	}

	BookMarkVsCommand info;
	info.pCmd = pCmd;	
	info.vBookMark = vBookMark;	
	m_mapBookMarksVsCommands.Add(info);		
}

variant_t GetBookMark(CGDataBaseCommand* pCmd)
{
	for(int i = m_mapBookMarksVsCommands.GetSize() - 1; i >=0 ; i--)
	{
		if(m_mapBookMarksVsCommands[i].pCmd  == pCmd)
		{
			return m_mapBookMarksVsCommands[i].vBookMark;
		}
	}	

	_variant_t vt;
	vt.vt = VT_EMPTY;

	return vt;
}

void UpdateBookMarks(_variant_t vOldBookMark, _variant_t vNewBookMark)
{
	for(int i = m_mapBookMarksVsCommands.GetSize() - 1; i >=0 ; i--)
	{
		if(m_mapBookMarksVsCommands[i].vBookMark == vOldBookMark)
		{
			m_mapBookMarksVsCommands[i].vBookMark = vNewBookMark;
		}
	}	
}


CGDBEditRowCommand::CGDBEditRowCommand(_RecordsetPtr pSet, const CDDXFields& fields, CDataGrid* pGrid) 
					: CGDataBaseCommand(pSet, fields)
{
	m_pGrid = pGrid;
	
	m_undoDDXFields.RemoveAll();
	m_undoDDXFields.Append(fields);	
}


BOOL CGDBEditRowCommand::Execute()
{	
	BOOL bRet = FALSE;	

	_variant_t vBookMark = GetBookMark(this);			
	if(vBookMark.vt == VT_EMPTY) // first time
	{		
		SetCommandInfoAt(this, m_pSet->Bookmark);
	}
	else
	{
		m_pSet->Bookmark = vBookMark;
	}
	
	try
	{
		m_undoDDXFields.ReadData(m_pSet);
		
		if( m_DDXFields.WriteData(m_pSet)!=-1)
		{
			try
			{			
				m_pSet->Update();
				
				if(m_pGrid)
				{
					m_pGrid->SetRowFocus(m_pSet->AbsolutePosition);
				}
					
				bRet = TRUE;
			}
			catch(...)
			{
			}			
		}
	}
	catch( _com_error &e )
	{

		CString mes1,mes2,mes3,mes4;

		mes1.Format(_T("Error:%08lx.\n"), e.Error());
		mes2.Format(_T("ErrorMessage:%s.\n"), e.ErrorMessage());
		mes3.Format(_T("Source:%s.\n"), (LPCTSTR) _bstr_t(e.Source()));
		mes4.Format(_T("Description:%s.\n"), (LPCTSTR) _bstr_t(e.Description()));
		MessageBox(NULL, mes1+mes2+mes3+mes4,_T("Undo Error"),MB_ICONERROR);


		return FALSE;
	}		

					
	return bRet;
}
    
BOOL CGDBEditRowCommand::UnExecute()
{
	BOOL bRet = FALSE;
	
	try
	{		
		_variant_t vBookMark = GetBookMark(this);
		if(vBookMark.vt == VT_EMPTY) // first time
		{
			AfxMessageBox(_T("Invalid Command"));
		}
		else
		{
			m_pSet->Bookmark = vBookMark;
		}
		
		if( m_undoDDXFields.WriteData(m_pSet)!=-1)
		{
			try
			{
				m_pSet->Update();				

				if(m_pGrid)
				{
					m_pGrid->SetRowFocus(m_pSet->AbsolutePosition);
				}
				
				bRet = TRUE;				
			}
			catch(...)
			{
			}			
		}	
	}
	catch( _com_error &e )
	{

		CString mes1,mes2,mes3,mes4;

		mes1.Format(_T("Error:%08lx.\n"), e.Error());
		mes2.Format(_T("ErrorMessage:%s.\n"), e.ErrorMessage());
		mes3.Format(_T("Source:%s.\n"), (LPCTSTR) _bstr_t(e.Source()));
		mes4.Format(_T("Description:%s.\n"), (LPCTSTR) _bstr_t(e.Description()));
		MessageBox(NULL, mes1+mes2+mes3+mes4,_T("Undo Error"),MB_ICONERROR);


		return FALSE;
	}			
	
	return bRet;
}

CGDBAddRowCommand::CGDBAddRowCommand(_RecordsetPtr pSet, const CDDXFields& fields, CDataGrid* pGrid) 
					: CGDataBaseCommand(pSet, fields)
{
	m_pGrid = pGrid;
}

BOOL CGDBAddRowCommand::Execute()
{	
	BOOL bRet = FALSE;

	m_pSet->AddNew();
	if( m_DDXFields.WriteData(m_pSet)!=-1)
	{
		try
		{
			m_pSet->Update();

			_variant_t vBookMark = GetBookMark(this);
			if(vBookMark.vt == VT_EMPTY) // first time
			{
				SetCommandInfoAt(this, m_pSet->Bookmark);
			}
			else
			{
				UpdateBookMarks(vBookMark, m_pSet->Bookmark);
			}

			m_DDXFields.ReadData(m_pSet);			
			
			if(m_pGrid)
			{
				m_pGrid->Invalidate();
				m_pGrid->SetRowFocus(m_pSet->AbsolutePosition);
				m_pGrid->AddNew();
			}																								
			
			bRet = TRUE;
		}
		catch(...)
		{
		}			
	}
				
	return bRet;
}
    
BOOL CGDBAddRowCommand::UnExecute()
{
	BOOL bRet = FALSE;	
	
	try
	{
		_variant_t vBookMark = GetBookMark(this);
		if(vBookMark.vt == VT_EMPTY)
		{
			SetCommandInfoAt(this, m_pSet->Bookmark);
		}
		else
		{
			m_pSet->Bookmark = vBookMark;
		}		
		
		m_DDXFields.ReadData(m_pSet);

		int pos = m_pSet->AbsolutePosition;

		BOOL bBof = pos == 1;
		BOOL bEof = pos == m_pSet->GetRecordCount();
		
		m_pSet->Delete(adAffectCurrent);			
		m_pSet->Update();						
		
		if(m_pGrid)
		{
			m_pGrid->Invalidate();			
			m_pGrid->SetRowFocus(pos-1);
			if(bBof)
			{
				m_pSet->MoveNext();
			}
			if(bEof)
			{
				m_pSet->MovePrevious();
			}
			
			m_pGrid->SetRowCount(m_pSet->GetRecordCount() + 1);
		}

		bRet = TRUE;
	}
	catch( _com_error &e )
	{

		CString mes1,mes2,mes3,mes4;

		mes1.Format(_T("Error:%08lx.\n"), e.Error());
		mes2.Format(_T("ErrorMessage:%s.\n"), e.ErrorMessage());
		mes3.Format(_T("Source:%s.\n"), (LPCTSTR) _bstr_t(e.Source()));
		mes4.Format(_T("Description:%s.\n"), (LPCTSTR) _bstr_t(e.Description()));
		MessageBox(NULL, mes1+mes2+mes3+mes4,_T("Undo Error"),MB_ICONERROR);


		return FALSE;
	}	
	
	return bRet;
}


CGDBDeleteRowCommand::CGDBDeleteRowCommand(_RecordsetPtr pSet, const CDDXFields& fields, CDataGrid* pGrid) 
					: CGDBAddRowCommand(pSet, fields, pGrid), m_bFirstTimeExecution(TRUE)
{
}

BOOL CGDBDeleteRowCommand::Execute()
{	
	if(m_bFirstTimeExecution)
	{
		m_bFirstTimeExecution = FALSE;

		CString strDel,strErrorDesc;
		strDel.LoadString(IDS_GRID_DEL);
		CString strQuestion;

		strQuestion.LoadString(IDS_GRID_DEL_QUESTION);
		if (::MessageBox (AfxGetMainWnd()->GetSafeHwnd(), strQuestion, strDel,  MB_YESNO|MB_DEFBUTTON2 | MB_ICONQUESTION) == IDNO)
			return FALSE;				
	}
	
	BOOL bRet = CGDBAddRowCommand::UnExecute();	

	return bRet;
}

BOOL CGDBDeleteRowCommand::UnExecute()
{	
	BOOL bRet = CGDBAddRowCommand::Execute();	

	return bRet;
}  

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Kotha Technologies
Bangladesh Bangladesh
If you are not in - you are out !
- Chapter 1

Comments and Discussions