Problems with DAO coming with VC++ 4.1
Jari Porra -- Porra@msn.com Sunday, April 21, 1996 I SENT A FIRST VERSION OF THIS EARLIER, BUT I SEND THIS UPDATED NOTE NOW AS I HAVE FOUND OUT THAT AT LEAST FOR ME GOING BACK TO DAO COMING WITH VC++ 4.0 SEEMS TO BE THE ONLY (TEMP.) SOLUTION AT THE MOMENT: What to do when MFC application, after an update from 4.0 to 4.1 does not update mdb tables anymore? - Here's the description of the problem, and the only solution I managed to find (going back to DAO from VC++ 4.0 CD). Env: Win 95, MS Access 2.0 (due to having ADK 2.0 I keep using this), updating from VC++ 4.0 to 4.1 (same problem appeared also when testing with 2.0 mdbs converted to Access 7.0 mdb) Have you seen this: MFC Application which has been for long updating well mdb databases fails after having migrated from 4.0 to 4.1. and having recompiled the application with 4.1. Also installed the DAO coming with the 4.1 CD. CDaoRecordset::Update method fails at: //DAOCORE.cpp (I guess Microsoft has not cut and //line4618 pasted proper comment lines (get_ vs. put_)!): ... // Use DAO optimization. get_Collect will get the field object from // the fields collection and fetch the value DAO_CHECK(m_pDAORecordset->put_Collect( COleVariant(lpszName, VT_BSTRT), varValue)); ... Causing DAO Trace: DAO Call Failed. m_pDAORecordset->put_Collect( COleVariant(lpszName, VT_BSTRT), varValue) In file daocore.cpp on line 4618 scode = 800A0CC1 Error Code = 3265 Source = DAO.Fields Description = Item not found in this collection. First-chance exception in Accounts.exe: 0xE06D7363: Microsoft C++ Exception. I have tried this: - Watched that lpszName and varValue are OK in above failing call to DAO, so it gets a valid field and a valid value (updating any field in any form for any table seems to cause now the DAO failure above with messagebox "Item not found in this collection", DAO error 3265) - same error with 2.0 and 7.0 mdb (with win 95 and 4.1 dao) - enumerated the fields with GetFieldCount/GetFieldInfo in the application, which listed all 100+ fields so that they in principle seem to be OK available for DAO - also created a brand new small MFC Dao app (which made use of MS Access 2.0 mdb table with 116 fields, this also fails when moving to next record - and updating - with the same error!) - verified on 2 PCs C U R R E N T TEMP. S O L U T I O N ------------------------------------- Problem dissappeared only when I went back to old DAO from the 4.0 CD. As some DAO DLLs are never deleted on uninstall one has to be careful to delete the dll causing these problems manually after uninstalling dao 4.1 and before reinstalling dao 4.0 (del C:\Program Files\Common Files\Microsoft Shared\DAO\dao3032.dll). QUESTIONS --------- 1) Is this a generally known problem? 2) How to debug deeper into a DAO call when it seems to fail for no good reason (i.e. it does't find fields when trying to set value, even if it can enumarate the very same fields)? 3) Just for curioisty: are there varieties of version 4.1 or is the CD I am holding THE VERSION VC++ 4.1? Is there another 4.1 DAO3032.DLL not causing the problem. OK old 4.0 was from 20.9.95, 4.1 causing problems from 5.1.96. 4) How to make an application to be generally distributed to check which version of DAO is Ok in its environment. Can it use its own DAO3032.DLL without touching the shared DAO dir? 5) Can you use DAO coming with VC++ 4.1? 6) Your educated guess, what's going on here? This was not a *NICE* experience! Thank you for attending Regards Jari Porra
alberto.gimenez@vlc.servicom.es Wednesday, April 24, 1996 [Mini-digest: 2 responses] I have experimented the same problem. After much time of breaking me the head, I put me in touch with Microsoft Spain and transmitted me to the article Q139997 "FIX: 'Item not found in this collection' with MFC DAO Join" that it can be found in April MSDN or in Internet. This article says : > To work around this problem, use one of the following two techniques depending on the names of the affected tables and columns (the ones for which table qualifiers are necessary). If Table and Column Names Contain No Spaces ------------------------------------------- Remove the brackets that enclose the table and column names. The resulting reference should be of this form: Table.Column If Table and/or Column Names Contain Spaces ------------------------------------------- Don't remove the bracket delimiters or your application will throw an exception that indicates: Syntax error in query expression 'table name.column name'. Instead, you must override one of the existing overloads of the virtual function CDaoRecordset::SetFieldValue() as follows (assuming your CDaoRecordset is named CMyDaoRecordset): void CMyDaoRecordset::SetFieldValue(LPCTSTR lpszName, const COleVariant& varValue) { CString strNewName(lpszName); StripBrackets(strNewName, strNewName.GetBuffer(0)); strNewName.ReleaseBuffer(); CDaoRecordset::SetFieldValue(strNewName, varValue); } This override uses the StripBrackets member function of CDaoRecordset to remove the offending brackets and allows the search for the field in the field collection to succeed. < I removed the brackets and work fine. A greeting. -- Alberto Gimenez (alberto.gimenez@vlc.servicom.es) -----From: Jim LeavittJari I had the same problem, here's the solution: PSS ID Number: Q140599 Article last modified on 12-10-1995 4.00 WINDOWS NT --------------------------------------------------------------------- The information in this article applies to: - The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++, 32-bit Edition, version 4.0 --------------------------------------------------------------------- SYMPTOMS ======== The MFC DAO Classes contain methods that accept COleVariant arguments. For example, CDaoRecordset::Seek(), CDaoRecordset::SetFieldValue(), and CDaoRecordset::SetBookMark() accept COleVariant arguments. You may find that these functions do not perform correctly if you are building a non-UNICODE build of your application and you are assigning a string to a COleVariant and passing the variant to one of these methods. For example, look at the following code, which is shown in MFC Technote #53: COleVariant varFieldValue; rs.AddNew(); varFieldValue = _T("MSFT"); rs.SetFieldValue(_T("Customer_ID"), varFieldValue); varFieldValue = _T("Microsoft"); rs.SetFieldValue(_T("Customer_Name"), varFieldValue); rs.Update(); This code causes only the first letters of each string to be copied to the database with a non-UNICODE build. In this case, the letter M will be copied to both fields. CAUSE ===== MFC creates ANSI DAO objects when building non-UNICODE builds and creates UNICODE DAO objects when building UNICODE builds. For example, look at the following code in AfxDaoInit(): GUID guidEngine; #ifdef _UNICODE guidEngine = IID_IDAODBEngineW; #else guidEngine = IID_IDAODBEngine; #endif The ANSI DAO objects require ANSI BSTRs for any strings that they receive. When you initialize a COleVariant object using: COleVariant varFieldValue(_T("some string")); -or- COleVariant varFieldValue; varFieldValue = _T("MSFT"); the COleVariant will contain a UNICODE BSTR regardless of whether the build is UNICODE or non-UNICODE. This is not what DAO expects. RESOLUTION ========== There are two techniques you can use to initialize the COleVariant properly. If you are only concerned about setting the BSTR value of the COleVariant at construction time, use this code: COleVariant varFieldValue(_T("SomeString"), VT_BSTRT); The VT_BSTRT constant specifies that the BSTR will be a UNICODE BSTR with a UNICODE build and it will be a ANSI BSTR in a non-UNICODE build. If you need to change the value of the variant often, you may want to create a helper function: void FillVariant(COleVariant & var, LPCTSTR lpszSrc) { var.vt=VT_BSTR; if (lpszSrc==NULL) var.bstrVal=NULL; else { #ifndef _UNICODE int nLen = lstrlen(lpszSrc); var.bstrVal = SysAllocStringByteLen(lpszSrc, nLen); #else var.bstrVal = SysAllocString(lpszSrc); #endif } } STATUS ====== This behavior is by design. Additional reference words: 4.00 Seek SetFieldValue SetCacheStart SetBookMark SetParamValue KBCategory: kbprg kbprb KBSubcategory: MfcDao ============================================================================= Copyright Microsoft Corporation 1995. Jim Leavitt
Roelof Blom -- roelofb@xs4all.nl Saturday, April 27, 1996 At 09:27 21-04-96 UT, you wrote: > >I SENT A FIRST VERSION OF THIS EARLIER, BUT I SEND THIS UPDATED NOTE >NOW AS I HAVE FOUND OUT THAT AT LEAST FOR ME GOING BACK TO DAO >COMING WITH VC++ 4.0 SEEMS TO BE THE ONLY (TEMP.) SOLUTION AT THE >MOMENT: > >What to do when MFC application, after an update from 4.0 to 4.1 >does not update mdb tables anymore? - Here's the description of >the problem, and the only solution I managed to find (going back >to DAO from VC++ 4.0 CD). > >Env: Win 95, MS Access 2.0 (due to having ADK 2.0 I keep using this), >updating from VC++ 4.0 to 4.1 >(same problem appeared also when testing with 2.0 mdbs converted >to Access 7.0 mdb) > >Have you seen this: > >MFC Application which has been for long updating well mdb >databases fails after having migrated from 4.0 to 4.1. and >having recompiled the application with 4.1. Also installed >the DAO coming with the 4.1 CD. > >CDaoRecordset::Update method fails at: > >//DAOCORE.cpp (I guess Microsoft has not cut and >//line4618 pasted proper comment lines (get_ vs. put_)!): >... > // Use DAO optimization. get_Collect will get the field object from > // the fields collection and fetch the value > DAO_CHECK(m_pDAORecordset->put_Collect( > COleVariant(lpszName, VT_BSTRT), varValue)); >... > >Causing DAO Trace: > >DAO Call Failed. > m_pDAORecordset->put_Collect( COleVariant(lpszName, VT_BSTRT), varValue) > In file daocore.cpp on line 4618 > scode = 800A0CC1 >Error Code = 3265 >Source = DAO.Fields >Description = Item not found in this collection. >First-chance exception in Accounts.exe: 0xE06D7363: Microsoft C++ Exception. > >I have tried this: >- Watched that lpszName and varValue are OK in above failing call > to DAO, so it gets a valid field and a valid value > (updating any field in any form for any table seems to > cause now the DAO failure above with messagebox "Item not > found in this collection", DAO error 3265) >- same error with 2.0 and 7.0 mdb (with win 95 and 4.1 dao) >- enumerated the fields with GetFieldCount/GetFieldInfo in the > application, which listed all 100+ fields so that they > in principle seem to be OK available for DAO >- also created a brand new small MFC Dao app (which made use of > MS Access 2.0 mdb table with 116 fields, this also fails when > moving to next record - and updating - with the same error!) >- verified on 2 PCs > > C U R R E N T TEMP. S O L U T I O N >------------------------------------- >Problem dissappeared only when I went back to old DAO from the >4.0 CD. As some DAO DLLs are never deleted on uninstall one has >to be careful to delete the dll causing these problems manually >after uninstalling dao 4.1 and before reinstalling dao 4.0 (del >C:\Program Files\Common Files\Microsoft Shared\DAO\dao3032.dll). > > >QUESTIONS >--------- > >1) Is this a generally known problem? >2) How to debug deeper into a DAO call when it seems to fail > for no good reason (i.e. it does't find fields when trying > to set value, even if it can enumarate the very same fields)? >3) Just for curioisty: are there varieties of version 4.1 or is > the CD I am holding THE VERSION VC++ 4.1? > Is there another 4.1 DAO3032.DLL not causing the problem. > OK old 4.0 was from 20.9.95, 4.1 causing problems from 5.1.96. >4) How to make an application to be generally distributed to > check which version of DAO is Ok in its environment. Can it > use its own DAO3032.DLL without touching the shared DAO dir? >5) Can you use DAO coming with VC++ 4.1? >6) Your educated guess, what's going on here? > Jari, We use Access 7 MDB's and experienced the same problems. Its the square brackets around the field names in CDaoRecordset::DoFieldExchange that cause this problem. We came up with 2 solutions: 1. In the DoFieldExchange() member of your CDaoRecordset remove the square brackets that surround the field names. This means you have to update all your CDaoRecordset derived classes, and do this everytime ClassWizard generates a new CDaoRecordset derived class for you. 2. Override SetFieldValue and let it remove the brackets through a call to StripBrackets(). This is a lot of work for your code, because MFC puts the brackets around the field name just before it calls your SetFieldValue(), who's only job is to remove the brackets and call the base class implementation... Hope this helps, Roelof. Roelof Blom - roelofb@xs4all.nl DOMUS Software BV Amsterdam, The Netherlands
| Вернуться в корень Архива |