Solved

C++ GetFieldValue uniqueidentifier

Posted on 2008-10-08
7
1,420 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
  • 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
NAS Cloud Backup Strategies

This article explains backup scenarios when using network storage. We review the so-called “3-2-1 strategy” and summarize the methods you can use to send NAS data to the cloud

 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 125 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

Migrating Your Company's PCs

To keep pace with competitors, businesses must keep employees productive, and that means providing them with the latest technology. This document provides the tips and tricks you need to help you migrate an outdated PC fleet to new desktops, laptops, and tablets.

Question has a verified solution.

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

Data architecture is an important aspect in Software as a Service (SaaS) delivery model. This article is a study on the database of a single-tenant application that could be extended to support multiple tenants. The application is web-based develope…
In this article I will describe the Backup & Restore method as one possible migration process and I will add the extra tasks needed for an upgrade when and where is applied so it will cover all.
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 use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

813 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now