?
Solved

C++ GetFieldValue uniqueidentifier

Posted on 2008-10-08
7
Medium Priority
?
1,501 Views
Last Modified: 2013-11-20
I am using VC++ 6.0 and MFC

I select a recordset and then try using GetFieldValue.

This works except for when the field is of type uniqueidentifier (SQL Server 2005)

In that case, the following code fails:

 recset->GetFieldValue(_T("worklist_vuid"), mVar);

It crashes in dbcore.cpp in this function:

void* PASCAL CRecordset::GetDataBuffer(CDBVariant& varValue,

in which it is doing a switch on the field type, and it asserts because, it would seem, uniqueidentifier is not a type of field the MFC class recognizes.

So how do I capture a field value of this type into a CString in my MFC code?

Thanks
0
Comment
Question by:PMH4514
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
7 Comments
 
LVL 19

Expert Comment

by:LordOfPorts
ID: 22673669
I am not certain if this will be helpful however the version of the GetFieldValue function http://msdn.microsoft.com/en-us/library/5f8k59f9(VS.80).aspx you are using has a third optional parameter which by default forces the C data type to be determined based upon the SQL Server data type, try explicitly specifying the third parameter to avoid the automatic determination, according to the documentation SQL_C_CHAR can store any data type and would be worth a try:
recset->GetFieldValue(_T("worklist_vuid"), mVar, SQL_C_CHAR);

Open in new window

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22677713
I googled and found the following statement:

-------------------
The uniqueidentifier data type in SQL Server is stored natively as a 16-byte binary value ...
-------------------

So, you can't read it as string but have to read it as binary and convert manually to a string:

Replace the RFX_Text macro for that field by a RFX_Binary macro like

    RFX_Binary(pFx, _T("worklist_vuid"), m_vuid, 16)

where the m_vuid is a CByteArray member (and not CString).
 
0
 

Author Comment

by:PMH4514
ID: 22678126
itsmeandnobodyelse: - I'm having trouble figuring out how to do what you are saying.
Could you show me a complete code snippet for pulling the uniqueidentifier value out of the field 'worklist_vuid' into a variable I can then use like a CString (ie. for adding it as a label to MFC List controls etc..)

Are you saying something like this I think maybe?

CByteArray bVUID;
recset->GetFieldValue(RFX_Binary(pFx, _T("worklist_vuid"), bVUID, 16), mVar);


but what is pFx ??

Thanks for any clarifications, much appreciated.




0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 500 total points
ID: 22679606
>>>> Are you saying something like this I think maybe?

Sorry, I assumed you were using the - generated from wizard - CRecordset::DoFieldExchange which looks like

void CCustSet::DoFieldExchange(CFieldExchange* pFX)
{
   //{{AFX_FIELD_MAP(CCustSet)
   pFX->SetFieldType(CFieldExchange::outputColumn);
   RFX_Text(pFX, "Name", m_strName);
   RFX_Int(pFX, "Age", m_wAge);
   //}}AFX_FIELD_MAP
}

Here the RFX_ macros were used to exchange data from members to recordset or vice versa. If you invoke class wizard (CTRL+W) and choose your CRecordset derived class you should be able to bind your CRecordset to a table of the data source and the wizard would generate the YourSet::DoFieldExchange.

A - less comfortable - alternative to that is calling CRecordset::GetFieldValue yourself  (in the above DoFieldExchange the RFX_ macros have the calls included)

   recset->GetFieldValue(_T("worklist_vuid"), mVar, SQL_C_BINARY);

Then the mVar (a CDBVariant) should contain an array of bytes (unsigned char). Unfortunately, I don't know how to get the bytes from a CDBVariant. But, if you need help for this I could look into the RFX_Binary macro implementation which should have solved that issue.

Note, there should be macros as well which would convert the 16 binary bytes to a GUID string, but unfortunately I don't know much of GUIDs and how to handle them.

0
 

Author Comment

by:PMH4514
ID: 22679764
Thanks.. You also assumed I derived my own CRecordset class. I did not, is this something I must do to accomplish this? Aside from that I saw no need.  I'll explore a bit based on your comments.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22680603
>>>> I did not, is this something I must do to accomplish this?
It is more comfortable. And the wizard will do (nearly) all work for you ...

I found out that the CDBVariant is a union where - depending on type - different members were valid. In case of SQL_C_BINARY data, the m_dwType member of CDBVariant  is set to DBVT_BINARY (what you should check) and the m_pBinary member of the union is valid. The m_pBinary points to a CLongBinary which has a handle to global data - m_hData - and a length member - m_dwDataLength.

I assume there are some macros which would convert a CLongBinary to a CByteArray, but you also could retrieve a pointer to the data by calling GlobalLock. If you output the bytes in the byte  array as hex numbers you should have all digits of the GUID (VUID)  for that record - though not structured. I am sure there are some handy macros which would convert the binary to a string.

0
 

Author Comment

by:PMH4514
ID: 22680999
Interesting, I understand. I think I can get it from here, with the aid of this article I found as well:
http://www.codeguru.com/forum/showthread.php?t=142900

0

Featured Post

Get real performance insights from real users

Key features:
- Total Pages Views and Load times
- Top Pages Viewed and Load Times
- Real Time Site Page Build Performance
- Users’ Browser and Platform Performance
- Geographic User Breakdown
- And more

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In SQL Server, when rows are selected from a table, does it retrieve data in the order in which it is inserted?  Many believe this is the case. Let us try to examine for ourselves with an example. To get started, use the following script, wh…
This article explains how to reset the password of the sa account on a Microsoft SQL Server.  The steps in this article work in SQL 2005, 2008, 2008 R2, 2012, 2014 and 2016.
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question