Click here to Skip to main content
13,199,026 members (44,316 online)
Click here to Skip to main content
Add your own
alternative version


101 bookmarked
Posted 11 Apr 2000

CODBCRecordset class

, 6 Jan 2001
Rate this:
Please Sign up or sign in to vote.
CODBCRecordset class is intended to be full replacement of all ClassWizard generated CRecordset derived classes in MFC projects.


In a usual MFC database project we have a lot of CRecordset derived classes generated by ClassWizard. The class presented here, CODBCRecordset is a very easy to use replacement of all these CRecordset classes. CODBCRecordset is derived from CRecordset but it does not have hardcoded inside the number and the type of the database fields.

I have seen some implementations trying to solve this problem. But CODBCRecordset has at least two advantages:

  1. CODBCRecordset can be used not only to get values from the database, but to write values into the database using the MFC way.
  2. The other implementations cannot open simultaneously more than one recordset through one database connection when the database is MS SQL Server. In some cases this could be very big problem because opening a new connection is time and resources expensive.

Because CODBCRecordset is derived from CRecordset and uses its data exchange mechanism it is fully compatible with MFC ODBC class CDatabase .

Each field value is stored in a CDBField object. The CDBField class is inherited from CDBVariant and has some added functionality so it's simple to use.

CODBCRecordset and CDBField classes support all database data types. CDBField makes implicit type conversion where it is appropriate to supply the data in the requested format.

Here is a list of CODBCRecordset and CDBField methods:

CODBCRecordset class
ConstructorThe same as for CRecordset accepting CDatabase*
BOOL Open( LPCTSTR lpszSQL, UINT nOpenType, DWORD dwOptions ); Open the recordset
lpszSQL is a SQL statement that returns recordset
e.g. SELECT * FROM tablename
nOpenType is CRecordset open type, see CRecordset::Open()dwOptions is CRecordset options, see CRecordset::Open()

Note that lpszSQL and nOpenType have exchanged their positions compared to CRecordset::Open()

short GetODBCFieldCount() Returns number of the fields (columns) in the recordset. This method is defined in CRecordset .
int GetFieldID( LPCTSTR ) Returns a field index by given field name. It is case insensitive. CRecordset::GetFieldIndexByName() works, but is case sensitive.
CString GetFieldName( int ) Returns a field name by given field index
CDBField& Field( LPCTSTR )<br />CDBField& Field( int ) Through this method you can get a reference to the internal CDBField object corresponding to the specified column (See the CDBField class table for details about CDBField ).

There are two forms of the method - with argument of type LPCTSTR szName - specifying the name of the column, and int nID - specifying the index of the coulmn in the recordset.

These methods can be used as lvalue in expressions. Thus you can write values to the database.

CDBField& operator( LPCTSTR )<br />CDBField& operator( int ) The function operator is defined for easy of use of the class and just calls the corresponding Field() method

There are two forms of the function operator - with argument of type LPCTSTR szName - specifying the name of the column, and int nID - specifying the index of the coulmn in the recordset.

These can be used as lvalue in expressions. Thus you can write values to the database.

unsigned char GetChar()
All of these methods do the appropriate type conversions depending on their return value and the type of the underlying data in the database.

These methods just call Field().AsXXX()
(See the CDBField class table for details about CDBField).

There are two forms of these methods - with argument of type LPCTSTR szName - specifying the name of the column, and int nID - specifying the index of the coulmn in the recordset.

These cannot be used as lvalue in expressions.

CDBField class
ConstructorsNo public constructors. CDBField cannot be instantiated except by CODBCRecordset to be used in internal structures to support data exchange. These objects are accessible through CODBCRecordset methods.
unsigned char AsChar()
All of these methods do the appropriate type conversions depending on their return value and the type of the underlying data in the database (See the AsXXX methods table for data conversion rules).

There is no data type Int but AsInt() is equal to AsLong()

assignment operatorsThere are defined assignment operators accepting bool, unsigned char, short, int, long, COleDateTime and CString. So CDBField objects can be lvalues. There is no assignemt operator accepting CLongBinary because MFC does not support writing CLongBinary values into database. These assignment operators do appropriate conversions to the underlying database column data type except CLongBinary (See the assignment operators table for data conversion rules).
const CString& GetName() Returns the field name this object corresponds to.
Each of these return true if the field contains a value of the corresponding data type.

There is no data type Number but IsNumber() returns true if IsShort() || IsLong() || IsFloat() || IsDouble().

There is no data type Int but IsInt() returns true if IsLong() returns true.

Conversions made by AsXXX methods

Values in the database

Empty cells indicate the conversion is not available, thus code asserts.
Cells marked with * indicate conversion is available (See the Conversion algorithms table for data conversion rules).

Conversions made by assignment operators

Database Field Type

Argument of the assignment operator

boolunsigned charshortintlongfloatdoubleCOleDateTimeString
Empty cells indicate the conversion is not available, thus code asserts.
Cells marked with * indicate conversion is available (See the Conversion algorithms table for data conversion rules).
Conversion algorithms
String to Boolcomparing the first character of the string with 'T'
Char to Boolcomparing the character with 'T'
Bool to StringString = (bVal) ? 'T' : 'F'
Bool to CharChar = (bVal) ? 'T' : 'F'
String to Numberappropriate atoX() function
Number to StringCString::Format() method using the appropriate format specifier string
String to DateCOleDateTime::ParseDateTime() method
Date to StringCOleDateTime::Format() method

Examples of how to use CODBCRecordset

You should include the files ODBCRecordset.h and ODBCRecordset.cpp in your project.

I usually include this line in my StdAfx.h file.

#include "ODBCRecordset.h"

Here is a simple code showing how CODBCRecordset can be used.

CDatabase    db;
//    This connect string will pop up the ODBC connect dialog
CString        cConnect = "ODBC;";
db.Open( NULL,                //    DSN
     FALSE,                //    Exclusive
     FALSE,                //    ReadOnly
     cConnect,            //    ODBC Connect string
     TRUE                //    Use cursor lib

COleDateTime    dOrderDate;

CODBCRecordset    rs( &db );
rs.Open( "SELECT * FROM Orders \
    WHERE ORDER_DATE > 'jan 1 2000' \
for( ; ! rs.IsEOF(); rs.MoveNext() )
//    The choice is yours. You may choose whatever way
//    you want to get the values
    //    These return COleDateTime value
    dOrderDate = rs.GetDate( "ORDER_DATE" );
    dOrderDate = rs.Field("ORDER_DATE").AsDate();

    //    These make implicit call to AsDate()
    dOrderDate = rs("ORDER_DATE");
    dOrderDate = rs.Field("ORDER_DATE");

    //    Now edit the fields in the recordset
    rs("ORDER_DATE") = "jan 1 1999";    // Implicit conversion
    rs.Field("ORDER_DATE") = "jan 1 1999";  // Implicit conversion
}    //    for(....

If ORDER_DATE is stored in the database as datetime or compatible data type the value will be get directly.
If ORDER_DATE is stored in the database as string or compatible data type (char, varchar) the value will be converted via COleDateTime::ParseDateTime() method. If conversion fails, dOrderDate will be set to COleDatetime::invalid.

When opening a resultset generated by join statements it is possible to get 2 or more columns that have the same name. CODBCRecordset leaves the name of the first column intact but other repeated columns are renamed with adding the number this columns repeats the name. Not repeated column names are left intact. E.g.

SELECT * FROM Orders, Customers WHERE Orders.CUST_ID = Customers.ID

If the table Orders have a column with name ID and Customers have a column with name ID, CODBCRecordset will rename ID from Customers to ID2 and all other not repeating column names will be intact.

Well, here is a tip: Rename columns manualy to be sure what name they have, e.g.

SELECT Orders.*, Customers.ID as CUSTOMERS_ID
    FROM Orders, Customers 
    WHERE Orders.CUST_ID = Customers.ID

How does CODBCRecordset work?

CODBCRecordset allocates storage for all fields in the resultset and uses MFC Record Field eXchange mechanism like it has been inherited from CRecordset using ClassWizard.

</li />


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Stefan Chekanov
Software Developer (Senior) Brosix
Bulgaria Bulgaria
Stefan does programming since his early ages more than 20 years ago. Later he began programming at his work and now he is very happy to work his hobby. He owns a Master's degree in Computer Science.

During his professional career, Stefan has worked with many technologies. His programming experience includes C/C++, Java, C#, PHP, JavaScript, MFC, ATL, ASP, ASP.NET, TCP/IP, SQL. He has worked with different operating systems: Windows, Linux, Mac OS X, iOS, Android, Solaris, FreeBSD, NetBSD and QNX.

Currently his professional interests are in building large scale distributed systems that operate over the Internet. This involves building server components as well as developing system level software.

More information about his current work can be found here: - Enterprise Instant Messaging

Stefan is based in Plovdiv, Bulgaria. It is a very nice and peaceful place combined with an enjoyable weather.

Stefan has a wife and 2 children. He likes in his spear time to travel with his family to see new and interesting places.

You may also be interested in...

Comments and Discussions

QuestionUNICODE support for CODBCRecordset Pin
Kulman Nikita24-Sep-13 22:23
memberKulman Nikita24-Sep-13 22:23 
GeneralRecord Count Lmit Pin
mauromaggiali25-Mar-10 23:01
membermauromaggiali25-Mar-10 23:01 
I want to use this class to read/write data from a mysql database and one of my tables has 348 fields; as soon as I open recordset, it throw an error because the filed count is > 255.
Is there a way to turn around this limit?


GeneralVery nicely done Pin
JPDworkin13-Aug-09 3:18
memberJPDworkin13-Aug-09 3:18 
GeneralProblem in retreiving Long Binary data from Access Database Pin
perianayaki27-Jan-09 23:27
memberperianayaki27-Jan-09 23:27 
QuestionBinary object? Pin
Stefan Dahlin6-Feb-08 23:14
memberStefan Dahlin6-Feb-08 23:14 
GeneralSame here... Pin
kathalora25-Dec-07 15:32
memberkathalora25-Dec-07 15:32 
GeneralSmall enhancement for GetCFieldType(...) Pin
Tomb0129-Oct-07 0:01
memberTomb0129-Oct-07 0:01 
GeneralUnicode modifications Pin
holst_gustav31-Jul-06 21:14
memberholst_gustav31-Jul-06 21:14 
GeneralRe: Unicode modifications Pin
vss11126-Aug-15 1:57
membervss11126-Aug-15 1:57 
NewsDBEditor [modified] Pin
pahagol29-Jul-06 8:42
memberpahagol29-Jul-06 8:42 
GeneralOn record retrievals Pin
swapna_signsin11-May-06 1:00
memberswapna_signsin11-May-06 1:00 
GeneralDoBulkFieldExchange with CODBCRecordSet Pin
bassel_z22-Apr-06 1:32
memberbassel_z22-Apr-06 1:32 
Questionhow get the &quot;ntext&quot; field from MSSQL Serverusin CODBCRecordSet Pin
El.Protestanto11-Apr-06 21:29
memberEl.Protestanto11-Apr-06 21:29 
Questionhow do u get the data in the database to u'r edit boxes(Beginner) Pin
swapna_signsin6-Apr-06 21:35
memberswapna_signsin6-Apr-06 21:35 
Questionhow to use parameters? Pin
fbachan3-Mar-06 10:42
memberfbachan3-Mar-06 10:42 
Generaldeleting Records using CODBCRecordset... Pin
austincherian28-Jan-06 0:09
memberaustincherian28-Jan-06 0:09 
GeneralCrash Pin
Sue Lai2-Nov-05 16:40
memberSue Lai2-Nov-05 16:40 
GeneralPlz Help me! Pin
syed abbdul qavi27-Sep-05 22:24
membersyed abbdul qavi27-Sep-05 22:24 
GeneralInvalid Descriptor Index Pin
Crercio O. Silva19-Sep-05 9:22
memberCrercio O. Silva19-Sep-05 9:22 
GeneralRe: Invalid Descriptor Index Pin
pietervdm4-Jan-06 22:30
memberpietervdm4-Jan-06 22:30 
GeneralRe: Invalid Descriptor Index Pin
wavesss26-Apr-07 23:05
memberwavesss26-Apr-07 23:05 
GeneralRe: Invalid Descriptor Index Pin
Rob Grainger30-Jul-07 4:28
memberRob Grainger30-Jul-07 4:28 
GeneralRe: Invalid Descriptor Index Pin
Luis Alberto Cedeno Flores12-Apr-11 12:08
memberLuis Alberto Cedeno Flores12-Apr-11 12:08 
QuestionSQL_LONGVARCHAR as SQL_C_BINARY results in &quot;Data truncated&quot; exeption in VC6 Pin
MindWanderer30-Aug-05 20:54
sussMindWanderer30-Aug-05 20:54 
AnswerRe: SQL_LONGVARCHAR as SQL_C_BINARY results in &quot;Data truncated&quot; exeption in VC6 Pin
MindWanderer30-Aug-05 20:58
sussMindWanderer30-Aug-05 20:58 
Generalwill i established connection with SQL server 2k Pin
Anonymous21-Jul-05 19:29
sussAnonymous21-Jul-05 19:29 
Questionhow i can index the table Pin
rashaff12319-Apr-05 0:09
memberrashaff12319-Apr-05 0:09 
General3 Warnings and an error by useing this class in Visual C++ .NET 7.1 Pin
Silviu-Marius Ardelean10-Apr-05 23:39
sussSilviu-Marius Ardelean10-Apr-05 23:39 
QuestionThread safe class? Pin
Dlt7525-Mar-05 1:12
memberDlt7525-Mar-05 1:12 
AnswerRe: Thread safe class? Pin
punkah1-Aug-05 7:41
susspunkah1-Aug-05 7:41 
Generalediting records Pin
koen baeyens4-Dec-04 2:55
memberkoen baeyens4-Dec-04 2:55 
GeneralRe: editing records Pin
ajl87918-Sep-05 17:17
memberajl87918-Sep-05 17:17 
GeneralConnect without DSN Pin
Jigar Mehta15-Nov-04 18:33
memberJigar Mehta15-Nov-04 18:33 
GeneralOut of Memory (95 fields) Pin
rdt3312-Nov-04 8:34
memberrdt3312-Nov-04 8:34 
GeneralOne problem Pin
Cui Sheng25-Sep-04 1:12
memberCui Sheng25-Sep-04 1:12 
GeneralA small bug in the implementation Pin
Antti Keskinen1-Mar-04 3:24
memberAntti Keskinen1-Mar-04 3:24 
GeneralRe: A small bug in the implementation Pin
urT25-Mar-04 8:13
memberurT25-Mar-04 8:13 
GeneralNew record, existing table Pin
RPGuard572-Feb-04 5:03
memberRPGuard572-Feb-04 5:03 
GeneralRe: New record, existing table Pin
LupinTaiwan8-Feb-06 14:43
memberLupinTaiwan8-Feb-06 14:43 
GeneralConnection Dialog Pin
craigsmith00722-Jan-04 5:05
membercraigsmith00722-Jan-04 5:05 
GeneralRe: Connection Dialog Pin
McNito24-Aug-04 14:00
memberMcNito24-Aug-04 14:00 
GeneralRe: Connection Dialog Pin
Anonymous18-May-05 6:38
sussAnonymous18-May-05 6:38 
GeneralParameters don't work Pin
Srikanth Garlapati18-Jan-04 22:49
memberSrikanth Garlapati18-Jan-04 22:49 
GeneralMessage in output window Pin
FASTian12-Jan-04 22:17
memberFASTian12-Jan-04 22:17 
GeneralUNICODE Pin
fill14-Dec-03 22:27
memberfill14-Dec-03 22:27 
GeneralRe: UNICODE Pin
Anonymous7-Feb-05 23:47
sussAnonymous7-Feb-05 23:47 
GeneralRe: UNICODE Pin
El.Protestanto10-Apr-06 3:59
memberEl.Protestanto10-Apr-06 3:59 
QuestionHow to realize the parameter query? Pin
Scott An20-Jul-03 16:46
memberScott An20-Jul-03 16:46 
Questionhow to insert a new record into an empty table? Pin
redark11-Jul-03 16:30
memberredark11-Jul-03 16:30 
AnswerRe: how to insert a new record into an empty table? Pin
John M. Drescher11-Jul-03 18:51
memberJohn M. Drescher11-Jul-03 18:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171020.1 | Last Updated 7 Jan 2001
Article Copyright 2000 by Stefan Chekanov
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid