• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1531
  • Last Modified:

C++ GetFieldValue uniqueidentifier

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
PMH4514
Asked:
PMH4514
  • 3
  • 3
1 Solution
 
LordOfPortsCommented:
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
 
itsmeandnobodyelseCommented:
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
 
PMH4514Author Commented:
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
itsmeandnobodyelseCommented:
>>>> 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
 
PMH4514Author Commented:
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
 
itsmeandnobodyelseCommented:
>>>> 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
 
PMH4514Author Commented:
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

NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now