Manipulating Data Records in Win CE
We are going to continue in our exploration of CE native database functionality by learning how to manipulate specific individual records. To this end, we'll be looking at a bit more of the code from "BetterBirthdays," the example program provided with the last lesson.
Editor's note: Check out Nancy's last article, Flexible Data Access, Powerful Subtleties, for more on the "BetterBirthdays" example.Deleting a Record from the Database
To begin, let's examine the ways in which we can use a record's CEOID, which is returned by a successful call to CeSeekDatabase(). (Note that in the example code, we saved this value in the global variable globalRecOID.)
Deleting a record is a straightforward operation, so we will start there. Below is a fragment of code from the message switch of the BirthdayDlgProc() function:
case IDC_DELETE: //open the database globalHDB = CeOpenDatabase (&globalCEOID, NULL, 0, 0, NULL); //delete the record CeDeleteRecord(globalHDB, globalRecOID ); //close the database CloseHandle( globalHDB ); globalHDB = 0; //re-init dialog ctrls InitDlgCtrls(hDlg); break;
To delete a record, we use athe simplest form of the CeOpenDatabase() function, identifying the database with the previously saved CEOID, globalCEOID, and setting all remaining parameters to zero. Using the handle to the database returned by CeOpenDatabase(), and the record CEOID saved after the prior call to FindBirthday(), we delete the record with a call to FindBirthday(), we delete the record with a call to CeDeleteRecord(), and then close the database.
Modifying an Existing Record
We also can access a record by CEOID in order to make modifications. Implementing this capability requires only a few enhancements to the AddBirthdayReminder() function. We used AddBirthdayReminder() in the first example program, BirthdayReminder. Because this new version of the function is similar in many ways to the original version, we'll just highlight the changes here.
First, notice that we have added an item to the original function's parameter list. The new parameter, an int, is used as a flag. It can assume one of two values: ADD_REC or UPDATE_REC. The value of this flag determines whether the function adds a new record or updates an existing record.
BOOL AddBirthdayReminder( HWND hDlg, int iAddUpdateFlag ){
Another change is that in this version of the program, we no longer store the birth date as the SYSTEMTIME structure that is returned by the dialog's Date Picker control:
//retrieve birthdate from the date time control hwndWhen = GetDlgItem(hDlg,IDC_WHEN); memset( &SysTime, 0x0, sizeof(SysTime)); DateTime_GetSystemtime(hwndWhen,&SysTime); //translate to filetime format SystemTimeToFileTime( &SysTime, &ftBirthday );
Rather, we convert the SYSTEMTIME value to a FILETIME. The FILETIME format is much more efficient, for two reasons. First, it encodes all the information in the SYSTEMTIME structure in a single DWORD, saving a great deal of storage space. Second, the CE native database type CEVT_FILETIME directly supports FILETIME values, so its translated value can be stored directly in the CEVALUNION member val.filetime. Here's the new CEPROPVAL structure initialization for this property:
//next, we write the "when" value into a property //write the prop id : ce type + index pRecord[1].propid = MAKELONG(CEVT_FILETIME , 1) ; //now put the FILETIME structure in the value //union for this property. pRecord[1].val.filetime = ftBirthday;
When we write the record to the database, one of two circumstances will prevail: Either we will be creating a new record at the end of the database, or we will be updating an existing record that we can precisely and immediately locate by CEOID. For this reason, we can do a simple database open operation:
//open the database
globalHDB = CeOpenDatabase (&globalCEOID, NULL, 0, 0, NULL);
rc = GetLastError();
If we detect that this is a record addition, we seek to the end of the database and write the record:
if( iAddUpdateFlag == ADD_REC )
{
//set oid parm to 0 to create a new rec
CeWriteRecordProps(globalHDB, 0, NUMBER_BIRTHDAY_PROPS,
pRecord);
}
If, instead, this is an update, we don't have to seek at all. We simply reference the existing record through its previously retrieved and saved CEOID, and write the new values directly into it:
else
{
//set oid parm to value set by "Find"
CeWriteRecordProps(globalHDB, globalRecOID,
NUMBER_BIRTHDAY_PROPS, pRecord);
}
Page 1 of 2
This article was originally published on May 5, 2004