|
I've a table in an Access database with an AutoNumber field. When I add a row to the table through a CRecordset object, I want to know the value of the AutoNumber field. I've read various articles on how this is done, but none of them work. The code basically looks like:
CMyRecordset set;
CDBVariant bookmark;
set.Open(AFX_DB_USE_DEFAULT_TYPE, NULL, CRecordset::useBookmarks);
set.AddNew();
set.field1 = 123;
set.field2 = 456;
...
set.GetBookmark(bookmark);
not been updated
set.Update();
the current one
set.Requery();
set.SetBookmark(bookmark); I successfully use bookmarks in other areas of the program when editing rows. I populate a listbox with each record in a recordset and assign the AutoNumber field using SetItemData() . When an item in the listbox is selected and the Edit button is clicked, I have the correct bookmark and can then use SetBookmark() and Edit() successfully. Using this scenario, if a newly added listbox item does not have a correct bookmark associated with it, SetBookmark() cannot be used prior to Edit() or Delete() calls. In other words, I have no way to navigate to the desired record.
Any ideas for this long-winded request?
Thanks,
DC
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
In theory - you need to obtain an exclusive lock to your datasource (I don't know how to do this because depending on ODBC drivers/ADO vrs DAO/etc. it changes). Then do the insert. Then query for MAX on the ID column. This will give you access to the newly inserted record. Then unlock it.
|
|
|
|
|
Terry O`Nolley wrote:
In theory - you need to obtain an exclusive lock to your datasource...
I'll try this, but I'm not following your logic. What would an exclusive lock on a single-user database have to with being able to query an AutoNumber field of a newly-added record?
I guess my main concern is that the dozen or so examples I looked at on MSDN and the Internet all showed basically the same approach: after an Update() , get the bookmark, call Requery() , set the bookmark, get the AutoNumber field value. The problem seems to be that after the call to Update() , the recordset is positioned back at the first record.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
DavidCrow wrote:
I'll try this, but I'm not following your logic. What would an exclusive lock on a single-user database have to with being able to query an AutoNumber field of a newly-added record?
I didn't realize it was a single-user DB.
If it is a single user DB then you don't need the lock. Just do the insert and query for MAX ID.
If your ID field is an auto-number, then the MAX will be the newly inserted record.
Using LOCK prevents other records from being inserted while you do your insert.
|
|
|
|
|
after update you are requerying and setting the bookmark. this is wrong.
you can get bookmark of a current record after you update. and bookmarks are valid only for navigating in the current recordsets. once you close and reopen or requery then the bookmarks get vanished. you should call recordset.canbookmark() to check whether it is possible to bookmark or not. use CDatabase::GetBookmarkPersistence.
always use exception handling in database programming to get the actual cause of erro.
never say die
|
|
|
|
|
sam India wrote:
after update you are requerying and setting the bookmark. this is wrong.
Please explain.
sam India wrote:
you can get bookmark of a current record after you update.
Which is what I am doing.
sam India wrote:
and bookmarks are valid only for navigating in the current recordsets. once you close and reopen or requery then the bookmarks get vanished. you should call recordset.canbookmark() to check whether it is possible to bookmark or not. use CDatabase::GetBookmarkPersistence.
As I already indicated, bookmarks are used elsewhere so CanBookmark() was omitted from the code snippet. I have used CheckBookmarkPersistence() to verify that bookmarks support the SQL_BP_SCROLL , SQL_BP_UPDATE , and SQL_BP_DELETE operations.
sam India wrote:
always use exception handling in database programming to get the actual cause of erro.
Exception handling is in place. I omitted it from the code snippet for brevity.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
program for trnslation code from owl to mfc
|
|
|
|
|
|
Does Object Windows Library still exist?
|
|
|
|
|
I think Borland have migrated it to VCL
Sonork 100.41263:Anthony_Yio
|
|
|
|
|
My own experience in doing this once is that you are better rewriting the program. In some situations, the architecture is so different, if you try to replicate it, it will really mess you up.
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
I am a student of B.C.S. i want to make a interface to my modem. so that i can check the cli like numbers of phone came.
If any body can help me in it i will be thankful so well.
Please also send me the Modem System Level Architecture
Good Bye
nhb
|
|
|
|
|
You couldn't find anything here[^]?
- Nitron
"Those that say a task is impossible shouldn't interrupt the ones who are doing it." - Chinese Proverb
|
|
|
|
|
I think he/she wants to get the caller id which is not in that list. I did this in the past, but I beleive there is no standard for this. For me I opened a terminal window to the modem and when a call came in it would appear on the terminal. I detected this extracted the caller id and sent it to my main program. This was a vb program yuck.... I wrote it only to begin to learn vb.
John
|
|
|
|
|
You can get Caller indentification info from LINECALLINFO struct, look up TAPI in MSDN
Peter Molnar
|
|
|
|
|
Couldn't find a better place to post the question, feel free to direct me to a better place...
Needing to automate our application testing using a keystroke/mouseclick recorder for playing back user events.... I thought there was something called Microsoft Test, but can't find any info on it...
Does Microsoft still makes something like this...??? If not, can someone suggest a popular automated testing tool for recording user events for playback...???
thanks
|
|
|
|
|
|
I am writing a scientific program that uses multiples threads to separate the GUI from the scientific simulation. I am using the CRT library so I am using the _beginthreadex() routine to start the "worker" thread. The problem is this: every once in a while (it is not reproducible, I have worked weeks on coming up with a reproducible situation but have never been successful) the _beginthreadex() routine will return NULL. When I check the error using GetLastError(), it states that there is not enough memory to run the thread. Once this error occurs, the thread cannot be started and the program must be restarted before it will successfully start the thread. When this error occurs the system is not out of memory and the program is not using much memory itself (as evidenced by the Windows task manager. This is an extremely frustrating problem for me and the other people that use this program. Has anyone had any similar experiences and can point me in the right direction for handling this problem.
Thanks,
Jay
|
|
|
|
|
jhoin wrote:
as evidenced by the Windows task manager
Are you absolutly sure of this? How much virtual memory is your process using? You may have run out of address space. Or have a highly fragmented address space such that there is no free block that is 1 MB to allocate a stack.
John
|
|
|
|
|
Thanks for you comments. No, I am not sure about this. A stupid question: How does one distinguish virtual memory and regular ram? How do I measure how much address space I have available? Oftentimes, the problem occurs right after the program starts up.
Jay
|
|
|
|
|
jhoin wrote:
How does one distinguish virtual memory and regular ram?
Virtual memory is the amount of RAM + swap files. You can have as large as a 4GB swapfile on every drive in your system. The address space of a single process is limited normally to 2GB with the largest block you can allocate being less than 1.3 GB because of memory fragmentation caused by dlls not loading sequentially in your address space.
jhoin wrote:
Oftentimes, the problem occurs right after the program starts up.
Then it is probably not a memory problem. How many threads are you spawning?
John
|
|
|
|
|
John,
Thanks for the primer on memory. I agree I don't think memory is a problem.
I am only spawning 3 threads at a time. It just doesn't make sense. The frequency of the problem depends on the machine it is being run on. I am at my wits end on this one.
Any arbitrary suggestions?
Jay
|
|
|
|
|
Are you putting in NULL for the Security descriptor parameter?
John
|
|
|
|
|
Post the code that spawns the thread including the parameters.
Keep a system log. I suspect that maybe one or more processes is taking up too much resources or that the issue has to do with system security.
Kuphryn
|
|
|
|
|
Here is the code which has been pared down a bit to get rid of unrelated initialization:
(one note: this routine itself was started as a thread so it is second in line and is trying to start a third thread.)
unsigned __stdcall micro_main(void *dummy)
{
unsigned threadID;
//other unrelated code
PSECURITY_DESCRIPTOR pSD;
SECURITY_ATTRIBUTES sa;
pSD = (PSECURITY_DESCRIPTOR) LocalAlloc( LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (pSD == NULL)
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL );
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
LocalFree( lpMsgBuf );
}
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL );
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
LocalFree( lpMsgBuf );
}
if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE))
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL );
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
LocalFree( lpMsgBuf );
}
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = TRUE;
MICRO_THREAD_SUB = (HANDLE)_beginthreadex( &sa, 0, &sub_main_MACRO_CONTROL, NULL, 0, &threadID );
if (MICRO_THREAD_SUB == 0)
{
// it is here that that I always get the error
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL );
MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
LocalFree( lpMsgBuf );
}
else
{
WaitForSingleObject(MICRO_THREAD_SUB,INFINITE);
CloseHandle(MICRO_THREAD_SUB);
}
// _endthreadex(0);
}
/*this is the thread which is called which immediately calls another thread-could that char com[200000]; be part of the problem? (it was used for some early debugging and no longer has any functionality.*/
unsigned __stdcall sub_main_MACRO_CONTROL(void *dummy)
{
char com[200000];
Run_Parser_Simulation(Sim->MACRO);
// _endthreadex(0);
return 0;
}
Thanks for looking at this. Regards,
Jay
|
|
|
|