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 Leavitt
Jari
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
| Вернуться в корень Архива
|