Click here to Skip to main content
15,885,214 members
Articles / Programming Languages / C++/CLI
Article

ADO.NET Primer using Managed C++

Rate me:
Please Sign up or sign in to vote.
4.24/5 (13 votes)
30 Jul 20029 min read 261.7K   57   34
A primer on using ADO.NET with Managed extensions for Visual C++ .NET

Abstract

The purpose of this article is to introduce data access and manipulation using ADO.NET with Managed C++. The code samples provided are simple examples of how the DataReader, DataSet, DataAdapter, DataRelation are used in creating a solution with SQL Server. This article is targeted towards the beginner with some knowledge of Managed C++ coding.

You will notice once you begin using the new object model that this is a complete paradigm shift from the traditional connection oriented data access technologies found in ADO and DAO. The new design of data access plays very well into an n-tiered application design reducing the need for connection and locking resources at the data source.

The relationships between the objects in the framework need to be understood before we can begin using them. You might consider the objects in the architecture as layers that sit on top of each other that providing support to the layers above. The DataSet is supported by the DataAdapter, the DataAdapter consists of some properties that are defined through command objects which sits on the Connection to the data source.

Although my description of the architecture as layers is a very simplistic view of the object model, the point is that ADO.NET although different than ADO, is not necessarily more complex.

The beauty of ADO.NET is that was design for the direction we were taking with ADO. That is, disconnected recordsets, data shaping, and XML for cross platform integration.

Not included in ADO.NET are the concepts of recordsets and cursors; and in its place are new objects to work with data: DataSets, DataAdapters, and DataReader.

A good primer on ADO.NET can easily fill a small book. This seven page article will not do ADO.NET any justice. I hope that at the end of this article you will have a good understanding on the ADO.NET framework and could begin using it.

This article is laid out in sections. The first section talks a bit on the architecture. The second section walks you through some code snippets. The final section covers the conclusion and some code examples on the topics we covered.

You will need Visual C++.NET to compile the examples. The examples connect to SQL Server using the Pubs database. To test the code you will need SQL Server and the Pubs database.

ADO.NET Architecture Overview

The ADO.NET architecture is a complete paradigm shift from ADO. The new object model is designed to be a disconnected approach to data access. At the implementation level, the most obvious change is the lack of recordsets and cursors in the framework. Once we get over the hurdle of knowing how to work without recordsets and cursors, we can see the advantage of using ADO.NET in n-tier designs.

Before we begin at looking at some code let me briefly go over the architecture of the new framework.

The architecture is comprised of two elements: .NET Data Provider and the DataSet. The components of the .NET Data Provider give us the mechanisms to connect to and work with our data source. The DataSet components provide us an in memory representation of the data source in the form of a result set similar to the disconnected recordset in ADO.

The .NET Data Provider library targets a database platform. The implementation section of this article talks a bit about the different libraries and where you might be able to find one you will need for your project.

The components that make up the .NET Data Provider are the Connection, Command,

DataReader
and the DataAdapter.The components found in the DataSet are collection objects for result sets (tables), rows, columns, constraints and relationships.

The

DataAdapter
sits between the DataSet and the Command objects. The purpose of the
DataAdapter
is to provide the interaction of the result set to the data source. The
DataAdapter
has four properties that dictate how the interaction is made. The properties are the SelectCommand, InsertCommand, UpdateCommand, and DeleteCommand. These properties hold the references to an instance of a Command object.

The DataAdapter uses the SelectCommand property to populate a result set in the DataSet. Changes that are made to the result set are analyzed by the

DataAdapter
once the Update method is called causing the appropriate command in one of the command properties to be issued. If the
DataAdapter
analyses a change and the command property has not been defined, an exception is thrown.

The DataReader object is used to retrieve data from a connection as quickly as possible. The data comes in a forward-only, read-only stream with the only memory required for the data is to only contain the current record.

The Connection and Command objects speak for themselves. The

Command
object defines an SQL command. An SQL command can be directly executed against the connection or referenced by the DataAdapter. Any results of a direct execution can be processed through a
DataReader
for processing.

The Connection object defines the connection to the data source. The

Connection
object and the DataReader are the only objects that need to be closed off once done with.

The DataSet

The DataSet is made up of collections exposing tables, rows, and columns. The collection of tables is commonly known as the result set and represented as the DataTable object. Each result set requires is own DataAdapter to maintain changes in the result set to the source table.

The result sets, rows, and columns in the collection are accessed by an index and the in-memory manipulation of a tables, rows, or columns is done using the objects DataTable, DataRow, DataColumn, and DataRelation.

Ultimately, the DataSet does not have any access to the underlying records sitting in the database. It only contains one or more copies of the data provided by the DataAdapter. It is the DataAdapter’s responsibility to initiate data modifications to the data source.

DataRelation

Part of the DataSet, the DataRelation object defines the relationship between the result sets of the DataSet. Defining a relationship creates a hierarchical dataset.

Working through the hierarchical result set requires setting the DataRow collection to retrieve a list of child records by calling GetChildRows method. This sounds more complicated than it should. I’ll walk you through a DataRelation example in the next section.

Implementation of ADO.NET

To begin using ADO.NET you need to include a reference to the System.Data.dll library in your source code. If you are using a DataSet you will need to also include a reference to System.Xml.dll.

MC++
#using <system.data.dll> // This is required for the ADO.NET Provider
#using <System.Xml.dll> // This is only required for the DataSet
 
using namespace System::Data;
using namespace System::Data::SqlClient;
using namespace System::Xml; // This is required for the DataSet

There are different .NET Providers for the various data sources. The table describes the namespace required for your target source.

Provider namespace

Target source

Notes

System.Data.SqlClient

SQL Server 7 and higher, and including the MSDE engine

 

System.Data.OleDb

Microsoft SQL Server 6.5 and earlier, any other OLE DB supported platform. Microsoft Access.

 

Microsoft.Data.Odbc

ODBC Compliant data source

Requires a download

System.Data.OracleClient

Oracle data source

Requires a download

After adding the reference and setting the scope using the namespace we could begin using the framework to create a connection to the source.

MC++
SqlConnection * mySQLConnection;
mySQLConnection = new SqlConnection
             (S"server=local;Trusted_Connection=yes;database=pubs;");
mySQLConnection->Open (); // Open up the connection

The SqlCommand object is just as simple to setup.

MC++
SqlCommand * mySQL;
mySQL = new SqlCommand (S"select * from authors", mySQLConnection);

Setting up the DataReader and begin extracting records is also simple.

MC++
SqlDataReader * myReader;
myReader = mySQL->ExecuteReader ();

while(myReader->Read ())
    Console::WriteLine(myReader->get_Item ("au_lname")->ToString ());

Once you are finished using the DataReader and Connection you should close them off calling the Close method.

MC++
myReader->Close ();
mySQLConnection->Close();
Before setting up a DataSet we need to create a DataAdapter. The DataAdapter is used to fill a DataSet with a result set and allow for changes made to the result set to be applied back to source.

The following code snippet demonstrates creating a DataAdapter and setting the SelectCommand property.

MC++
SqlDataAdapter * myDataAdapter;
myDataAdapter = new SqlDataAdapter();
myDataAdapter->SelectCommand = new SqlCommand 
                      (S"select * from authors",mySQLConnection);

As you can see, the SelectCommand property references an SqlCommand object containing an SQL Select command. This property is used to populate the DataSet with the results of the Select. The code to create a DataSet and populate it with a result set is as follows:

MC++
DataSet * myDataSet;
myDataAdapter->Fill (myDataSet,"authors");
// DataSet is populated using the Select * from authors command

Because the DataAdapter is responsible for making updates to the source, we have to set up the appropriate command property to allow for the update. The DataAdapter decides which property to execute against the source based on the changes made to the result set.

A DataAdapter is needed for each source table you will be making updates to.

The following code example shows how the InsertCommand property of the DataAdapter is prepared for a new record update. The example uses the parameters collection.

MC++
SqlParameter * myParameter;
myDataAdapter->InsertCommand = new SqlCommand(S"insert into authors " + 
                "(au_id,au_lName,au_fname,contract) values @auID, " +
                "@l_name, @f_name, @contract)", mySQLConnection);

//Set up the four parameters

//Au_id parameter
myParameter = myDataAdapter->InsertCommand->Parameters->Add(
    new SqlParameter ("@auID", SqlDbType::VarChar));
myParameter->SourceColumn = "au_id";
myParameter->SourceVersion = DataRowVersion::Current;

// l_name parameter
myParameter = myDataAdapter->InsertCommand->Parameters->Add(
    new SqlParameter("@l_name", SqlDbType::VarChar));
myParameter->SourceColumn = "au_lname";
myParameter->SourceVersion = DataRowVersion::Current;

// f_name parameter
myParameter = myDataAdapter->InsertCommand->Parameters->Add(
    new SqlParameter("@f_name", SqlDbType::VarChar));
myParameter->SourceColumn = "au_fname";
myParameter->SourceVersion = DataRowVersion::Current;

// contract parameter
myParameter = myDataAdapter->InsertCommand->Parameters->Add(
    new SqlParameter("@contract", SqlDbType::Bit));
myParameter->SourceColumn = "contract";
myParameter->SourceVersion = DataRowVersion::Current;
Once the InsertCommand property has been set, new records can be added to the data source. Calling the Update method on the DataAdapter will initiate the DataAdapter to analyze the changes to the result set and issue the appropriate command from one of the command properties. In this example the DataAdapter will decide to use the InsertCommand property to make the update.

The code to create a new record into the authors result set and source table is shown below.

MC++
DataRow * myRow;

myRow = myDataSet->Tables->Item["authors"]->NewRow ();

myRow->Item [0]=S"123-45-6799";       // Key
myRow->Item [1]=S"Bill";        // au_fname field
myRow->Item [2]=S"Ferreira";    // au_lname field
myRow->Item [8]=S"true";        // contract field

myDataSet->Tables->Item ["authors"]->Rows->Add (myRow);

// The DataAdapter will analyze the update as requiring an insert and 
// use the insert from the insertcommand property.
myDataAdapter->Update (myDataSet,"authors");

After you are done with the connection you will need to close it off.

MC++
mySQLConnection->Close();

If we were to deleted a record from the result set, the Update method of the DataAdapter would throw an exception since the DeleteCommand property has not been initialized with any SQL Delete command.

Creating a relationship between multiply result sets is simple using the DataRelation object. This code snippet shows how a DataRelation object is used to create a single relationship between two result sets.

MC++
DataRelation * myRelation;

myRelation = myDataSet->Relations->Add ("titleauthers",
myDataSet->Tables->Item ["authors"]->Columns->Item ["au_id"],
myDataSet->Tables->Item ["titles"]->Columns->Item ["au_id"]);

As you iterate through the authors result set, you would call the GetChildRows method to pull all the child rows.

MC++
DataRow      * myAuthorRow;
DataRow      * myTitlesRow[];

for(inti=0;>= myDataSet->Tables->Item ["authors"]->Rows->Count; i++) {
    myAuthorRow = myDataSet->Tables->Item ["authors"]->Rows->Item[i];
    Console::WriteLine("Author ID : {0}",myAuthorRow->Item ["au_id"]->ToString ());
    myTitlesRow = myAuthorRow->GetChildRows (myRelation);
    for(intx=0; x < myTitlesRow->Count ;x++)
      Console::WriteLine("Titles ID : {0}",
             myTitlesRow[x]->Item ["title_id"]->ToString ());
}

Conclusion

I hope that this article has been of some use to you. I have added some references I have found useful when programming with ADO.NET. What I have covered in this article only scratches the surface of the power and flexibility of ADO.NET.

Included are four complete examples I have selected to demonstrate the objects discussed in this article.

The first example creates and instantiates a connection and command object. The command object is executed on a DataReader where the results are pulled to the console.

The second example creates and instantiates a Connection, Command, DataAdapter, and DataSet object. The DataSet object is looped displaying the contents of a field.

The third example shows a new record insert.

The fourth example shows how a DataRelation object is used to create a relationship between to results sets of a DataSet.

To those who are familiar with ADO.NET, you could agree with me that there is so much more that should be covered in a primer. I needed to stick to the basics, otherwise it would turn into something like a development project without a scope, the whole world ends up getting sucked into it.

I would appreciate any of your feedback on this article. I could be reached by email at gbferreira@hotmail.com.

References:

  1. ADO.NET examples http://samples.gotdotnet.com/quickstart/latebreaking/
  2. Best Practices for Using ADO.NET http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmqqc/html/msmqbest.asp
  3. .NET Framework SDK Documentation

Source Code

MC++
// This is the main project file for VC++ application project
// generated using an Application Wizard.

#include "stdafx.h"
// Standard
#using <mscorlib.dll>
#using <System.dll>
#using <system.data.dll> // This is required for the ADO.NET Provider
#include <tchar.h>

using namespace System;
using namespace System::Data;
using namespace System::Data::SqlClient;

// This is the entry point for this application
int _tmain(void)
{
    SqlConnection      * mySQLConnection;
    SqlCommand         * mySQL;
    SqlDataReader      * myReader;
                      
    try
    {
        mySQLConnection = new SqlConnection(
            S"server=local;Trusted_Connection=yes;database=pubs;");
        mySQL = new SqlCommand (S"select * from authors",
            mySQLConnection);

        mySQLConnection->Open (); // Open up the connection
        myReader = mySQL->ExecuteReader ();

        while(myReader->Read ())
            Console::WriteLine(myReader->get_Item("au_lname")->ToString ()); 
    }
    catch(Exception * e)
    {
        Console::Write(e->ToString () );
    }
    __finally
    {
        myReader->Close ();
        mySQLConnection->Close();
    }
    return 0;
}
MC++
// This is the main project file for VC++ application project
// generated using an Application Wizard.

#include "stdafx.h"
// Standard
#using <mscorlib.dll>

#using <System.dll>
#using <system.data.dll> // This is required for the ADO.NET Provider
#using <System.Xml.dll> // This is required for the DataSet
#include <tchar.h>
using namespace System;
using namespace System::Data;
using namespace System::Xml; // This is required for the DataSet
using namespace System::Data::SqlClient;


// This is the entry point for this application
int _tmain(void)
{
    SqlConnection      * mySQLConnection;
    SqlDataAdapter     * myDataAdapter;
    DataSet      * myDataSet;
                                
    try
    {
        mySQLConnection = new SqlConnection(
            S"server=local;Trusted_Connection=yes;database=pubs;");
        myDataAdapter = new SqlDataAdapter();
        myDataSet = new DataSet();  
                 
        mySQLConnection->Open ();    // Open up the connection

        // Assign the SelectCommand with an SQL Select command
        myDataAdapter->SelectCommand = new SqlCommand (
            S"select * from authors",mySQLConnection);

        // Use the DataAdapter to fill the DataSet
        // A DataSet can be made up of many results. I called
        // this result authors. The DataAdapter will know to use 
        // the SelectCommand property to populate the DataSet.
        myDataAdapter->Fill (myDataSet,"authors");

        for(inti=0;i < myDataSet->Tables->Item ["authors"]->Rows->Count; i++)
            Console::WriteLine("Name:{0}",
                myDataSet->Tables->Item ["authors"]->Rows->Item[i]->Item 
                ["au_lname"]->ToString ());    
    }
    catch(Exception * e)  {
        Console::Write(e->ToString () );
    }
    __finally {
        mySQLConnection->Close();
    }
    return 0;
}
MC++
// This is the main project file for VC++ application project
// generated using an Application Wizard.

#include "stdafx.h"
// Standard
#using <mscorlib.dll>
#using <System.dll>
#using <system.data.dll>
#using <System.Xml.dll>

#include <tchar.h>

using namespace System;
using namespace System::Data;
using namespace System::Xml;
using namespace System::Data::SqlClient ;

// This is the entry point for this application
int _tmain(void)
{
    SqlConnection      * mySQLConnection ;
    SqlDataAdapter     * myDataAdapter;
    DataSet      * myDataSet;
    DataRow      * myRow;
    SqlParameter       * myParameter;
                      
    try
    {
        mySQLConnection = new SqlConnection 
            (S"server=local;Trusted_Connection=yes;database=pubs;");
        myDataAdapter = new SqlDataAdapter();
        myDataSet = new DataSet();  
                 
        // Open up the connection
        mySQLConnection->Open ();   

        // Assign the SelectCommand with an SQL select command
        myDataAdapter->SelectCommand = SqlCommand (S"select * from authors",
            mySQLConnection);
        myDataAdapter->InsertCommand =
            new SqlCommand (S"insert into authors (au_id,au_lName," + 
                            S"au_fname,contract) values (@auID,@l_name," + 
                            S"@f_name,@contract)",mySQLConnection);

        //Au_id parameter
        myParameter = myDataAdapter->InsertCommand->Parameters->Add(
            new SqlParameter("@auID", SqlDbType::VarChar));
        myParameter->SourceColumn = "au_id";
        myParameter->SourceVersion = DataRowVersion::Current;

        // l_name parameter
        myParameter = myDataAdapter->InsertCommand->Parameters->Add(
            new SqlParameter("@l_name", SqlDbType::VarChar));
        myParameter->SourceColumn = "au_lname";
        myParameter->SourceVersion = DataRowVersion::Current;

        // f_name parameter
        myParameter = myDataAdapter->InsertCommand->Parameters->Add(
            new SqlParameter("@f_name", SqlDbType::VarChar));
        myParameter->SourceColumn = "au_fname";
        myParameter->SourceVersion = DataRowVersion::Current;

        // contract parameter
        myParameter = myDataAdapter->InsertCommand->Parameters->Add(
            new SqlParameter("@contract", SqlDbType::Bit));
        myParameter->SourceColumn = "contract";
        myParameter->SourceVersion = DataRowVersion::Current;

        // Use the DataAdapter to fill the DataSet
        // A DataSet can be made up of many results. This result set I
        // called authors.
        // The DataAdapter will know to use the SelectCommand object
        // to populate the DataSet.
        myDataAdapter->Fill (myDataSet,"authors");

        myRow = myDataSet->Tables->Item["authors"]->NewRow ();
        myRow->Item [0]=S"123-45-6799";       // Key
        myRow->Item [1]=S"Bill";        // au_fname
        myRow->Item [2]=S"Ferreira";    // au_lname
        myRow->Item [8]=S"true";        // contract
        myDataSet->Tables->Item ["authors"]->Rows->Add (myRow);

        //we use insertcommand property for the update.
        myDataAdapter->Update (myDataSet,"authors"); 
    }
    catch(Exception * e) {
        Console::Write(e->ToString () );
    }
    __finally {
        mySQLConnection->Close();
    }
    return 0;
}
MC++
// This is the main project file for VC++ application project
// generated using an Application Wizard.

#include "stdafx.h"
// Standard
#using <mscorlib.dll>

#using <System.dll>
#using <system.data.dll>
#using <System.Xml.dll>

#include <tchar.h>

using namespace System;
using namespace System::Data;
using namespace System::Xml;
using namespace System::Data::SqlClient ;
using namespace System::Diagnostics;

// This is the entry point for this application
int _tmain(void)
{
    SqlConnection      * mySQLConnection ;
    DataRelation       * myRelation;
    SqlDataAdapter     * myDataAdapter;
    SqlDataAdapter     * myDataAdapterB;
    DataSet      * myDataSet;
    DataRow      * myAuthorRow;
    DataRow      * myTitlesRow[];
             
    try
    {
        mySQLConnection = new SqlConnection
            (S"server=local;Trusted_Connection=yes;database=pubs;");
        myDataAdapter = new SqlDataAdapter();
        myDataAdapterB = new SqlDataAdapter();
        myDataSet = new DataSet();  
                                    
        // Open up the connection
        mySQLConnection->Open ();   

        // Assign the SelectCommand with an SQL select command
        myDataAdapter->SelectCommand = new SqlCommand 
            (S"select * from authors",mySQLConnection);
        myDataAdapterB->SelectCommand = new SqlCommand 
            (S"select * from titleauthor",mySQLConnection);

        myDataAdapter->Fill (myDataSet,"authors");
        myDataAdapterB->Fill (myDataSet,"titles");

        myRelation = myDataSet->Relations->Add ("titleauthers",
            myDataSet->Tables->Item ["authors"]->Columns->Item ["au_id"],
            myDataSet->Tables->Item ["titles"]->Columns->Item ["au_id"]);

                          
        for(inti=0;>= myDataSet->Tables->Item ["authors"]->Rows->Count;i++) 
        {
            myAuthorRow = myDataSet->Tables->Item["authors"]->Rows->Item[i];
            Console::WriteLine("ID        : {0}",
                myAuthorRow->Item ["au_id"]->ToString ());
            myTitlesRow = myAuthorRow->GetChildRows (myRelation);
            for(intx=0; x<= myTitlesRow->Count-1 ;x++)
                Console::WriteLine("Titles ID       : {0}",
                myTitlesRow[x]->Item ["title_id"]->ToString ());
        }
                 
    }
    catch(Exception * e) {
        Console::Write(e->ToString () );
        Trace::WriteLine (e->ToString ());

    }
    __finally {
        mySQLConnection->Close();
    }
    return 0;
}

License

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


Written By
Web Developer
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCompile Error Pin
basma osman4-Aug-11 5:34
basma osman4-Aug-11 5:34 
GeneralMy vote of 1 Pin
h4ppyf4ce14-Sep-10 9:05
h4ppyf4ce14-Sep-10 9:05 
Generalhttp://samples.gotdotnet.com/quickstart/latebreaking/ [modified] Pin
KenThompson20-Mar-08 3:09
KenThompson20-Mar-08 3:09 
GeneralNice article, Thanks a lot. Pin
sundareswaran.senthilvel27-Apr-07 22:28
professionalsundareswaran.senthilvel27-Apr-07 22:28 
QuestionData Grid Pin
rob.bergman2-Mar-07 7:48
rob.bergman2-Mar-07 7:48 
Generalplease clear this doubt Pin
anant s.j4-Dec-06 0:26
anant s.j4-Dec-06 0:26 
GeneralConstraint Column-by-Column not Row-by-Row. Pin
mr6024-Dec-03 6:21
mr6024-Dec-03 6:21 
Generalheeeeeeeeeeelp! :) Pin
Anonymous26-Nov-03 0:50
Anonymous26-Nov-03 0:50 
Generaljanezi Pin
janezi16-Aug-03 12:43
janezi16-Aug-03 12:43 
GeneralVery strange comment... Pin
Aldamo23-Sep-03 18:12
Aldamo23-Sep-03 18:12 
Questionwhere does managed come in? Pin
chymke9-Jun-03 5:15
chymke9-Jun-03 5:15 
AnswerRe: where does managed come in? Pin
chymke9-Jun-03 5:32
chymke9-Jun-03 5:32 
Generalneed help~~ Pin
excalvin23-Feb-03 4:00
excalvin23-Feb-03 4:00 
GeneralRe: need help~~ Pin
excalvin23-Feb-03 4:05
excalvin23-Feb-03 4:05 
GeneralRe: need help~~ Pin
Bill Ferreira23-Feb-03 15:06
Bill Ferreira23-Feb-03 15:06 
GeneralRe: need help~~ Pin
Bill Ferreira23-Feb-03 15:17
Bill Ferreira23-Feb-03 15:17 
GeneralRe: need help~~ Pin
excalvin24-Feb-03 8:37
excalvin24-Feb-03 8:37 
Generalneed help Pin
excalvin23-Feb-03 3:55
excalvin23-Feb-03 3:55 
GeneralLess functionality than ADO Pin
MarkT18-Nov-02 17:56
MarkT18-Nov-02 17:56 
GeneralRe: Less functionality than ADO Pin
Christian Graus18-Nov-02 19:18
protectorChristian Graus18-Nov-02 19:18 
GeneralSqlDataReader : I need to assign retrieved value to C++ variable Pin
Doug13-Oct-02 13:02
Doug13-Oct-02 13:02 
Bill, thanks for your article. It certainly got me started.

May I ask 2 questions on your DataReader example?

1. Where a parameter is a text string, it is prefixed by 'S' eg.
mySQL = new SqlCommand (S"select * from authors",
mySQLConnection);

What is the 'S' for? My code seems to work without it - a CString passed as a parameter seems to work fine.


2. The whole purpose of retrieving values in my code is to manipulate them, not to display them on the screen.

Again, from your code:

while(myReader->Read ())
Console::WriteLine(myReader->get_Item("au_lname")->ToString ());


What I really need to do is to assign the item retrieved to a C++ variable eg.

int halfhrSQL = myReader->get_Item(3);

This gives the C2440 compile error: cannot convert from 'System::Object __gc *' to 'int'.

No matter what cast I use, I cannot get around the error.

Please help if you can.

Thanks, Doug (New Zealand)

Doug
GeneralRe: SqlDataReader : I need to assign retrieved value to C++ variable Pin
Bill Ferreira14-Oct-02 15:42
Bill Ferreira14-Oct-02 15:42 
GeneralRe: SqlDataReader : I need to assign retrieved value to C++ variable Pin
Bill Ferreira15-Oct-02 5:12
Bill Ferreira15-Oct-02 5:12 
GeneralRe: SqlDataReader : I need to assign retrieved value to C++ variable Pin
Doug15-Oct-02 12:12
Doug15-Oct-02 12:12 
GeneralRe: SqlDataReader : I need to assign retrieved value to C++ variable Pin
Bill Ferreira15-Oct-02 18:51
Bill Ferreira15-Oct-02 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.