Solved

C++ GetFieldValue uniqueidentifier

Posted on 2008-10-08
7
1,394 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
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
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

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Suggested Solutions

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…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
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.

743 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

15 Experts available now in Live!

Get 1:1 Help Now