Tải bản đầy đủ - 0 (trang)
Chapter 35: Programming ADO.NET Using Managed C++

Chapter 35: Programming ADO.NET Using Managed C++

Tải bản đầy đủ - 0trang

Overview

Overthelastfewyears,theMicrosoftplatformhasaccommodatedan

alphabetsoupofacronymsrepresentingvariousdataaccess

technologies,includingODBC(OpenDatabaseConnectivity),DAO(Data

AccessObjects),OLEDB(OLEDatabase),andADO(ActiveXData

Objects),whichuntilafewyearsagowasthepreferreddataaccess

technologyfortheMicrosoftplatform..NEThaschangedthat.

ADO.NETwillundoubtedlybethedataaccesstechnologyofchoicefor

modernapplicationsrunningunder.NET.ADO.NETisthemanagedcode

alternativetotraditionalADO.Thischapterisallaboutdataaccessunder

.NET.We'lllookatconnectingtodatabases,issuingcommandsto

databases,readingdataoutofdatabases,andmanagingdatasetsusing

ADO.NET.



ManagedProviders

AsyousawinChapter31,.NETisbasedonacommonruntimeengine

forallsoftwarerunningontheplatform.Thecommonlanguageruntime

takesgoodcareofyourcode.Itmanagesmemoryforyou,provides

interopservicesforyou,andmakesyourcodeexecutesafelyand

securely.

Theruntimedoesn'tprovidenativedataaccessfunctionality,but.NET

shipswithapairofmanageddatabaseproviders.Themanaged

providersarerepresentedbyseveralclassesthataremembersofthe

commonruntimeclasslibrary.Thedataaccessclassesareknown

collectivelyasADO.NET.

TheADO.NETDataReaderclassenablesyoutoretrieveaforward-only

andread-onlystreamofdatafromadatabase.TheDataSetclass

providesanin-memorycopyofdataretrievedfromadatabase.Youcan

thinkofaDataSetobjectasadisconnectedrecordsetinADO.ADO.NET

currentlyhasnoprovisionforserver-sidecursors.Someapplications

don'tneedthiscapability.Anyapplicationsthatrequireserver-side

cursorscanusetheclassicADOrecordsetthroughtheCOMinterop

layer.ThesamplesaccompanyingVisualStudio.NETincludeanADO

interopexample.TheexampleisincludedintheMicrosoftVisualStudio

.NET\FrameworkSDK\Samples\Technologies\Interop\Basic\ASPXToADO

directory.



.NETManagedProviders

AsfarasADO.NETisconcerned,therearebasicallytwokindsof

databases:MicrosoftSQLServerdatabasesandallotherdatabasesthat

implementOLEDB.TheSQLServermanagedproviderclassesrun

withinthecommonlanguageruntime;theOLEDBmanagedprovider

usesnativeOLEDBandtheCOMinteroplayertoestablishaconnection

toadatastore.

ADO.NETincludesthefollowingbasicfunctionalityforworkingwith

databases:creatingdatasets,connectingtodatabases,issuing

commands,readingdatastreams,andusingdataadapterstoexchange



databetweenadatasourceandadataset.ADO.NETdividesthe

functionalityintointerfacesandimplementations.Thatis,there'sasingle

connectioninterface,asinglecommandinterface,andasingledata

adapterinterface.However,ADO.NETfurnishesseparate

implementationsofeachoftheseinterfaces.Themanageddata

providersaregenerallydividedintotheSystem::Data::SqlClient

namespaceandtheSystem::Data::OleDbnamespace.Table35-1shows

theADO.NETinterfacesandtheirseparateimplementations.

Table35-1:ADO.NETInterfacesandTheirImplementations

Interface



SQLServer

Implementation



OLEDBImplementation



IDbConnection SqlConnection



OleDbConnection



IDataAdapter



SqlDataAdapter



OleDbDataAdapter



IDbCommand



SqlCommand



OleDbCommand



IDataReader



SqlDataReader



OleDbDataReader



IDataRecord



SqlDataRecord



OleDbDataRecord



IDataParameter SqlDataParameter



OleDbDataParameter



Figure35-1showstherelationshipbetweentheADO.NETmanaged

providers,SQLServer,OLEDBproviders,andCOM.



Figure35-1:Therelationship

betweentheADO.NETmanagedproviders,SQLServer,OLEDB

providers,andCOM.



WorkingwiththeProviders

Let'stakealookatwhatittakestoconnecttoadatabaseandexecute

somecodeusingADO.NETandmanagedC++.Thegeneraloperating

modeforADO.NETistoconnecttoadatabase,issueacommand,and

thenexaminetheresults.We'llexamineconnectingtoadatabasefirst.



ConnectingtotheDatabase

TheSqlConnectionclassandtheOleDbConnectionclassimplement

IDbConnection,whichprovidesmethodsforopeningadatabase

connectionandforstartinglocaltransactionsprogrammatically.

YousawinChapter31thatgarbagecollectionisnondeterministic,which

meansyoudon'tknowwhen(orevenif)amemoryallocationwillbe

collected.Forthatreason,youshouldcloseADO.NETconnections

explicitlywhenthey'renolongerneeded(ratherthenclosingthemina

destructorsomewhere).IDbConnection::Closeisthemethodfor

accomplishingthistask.YoucanalsocallDisposeontheconnection

object,whichwillalsoclosetheconnection.UsuallytheOpenandClose

(orDispose)callslivewithinatry/catchblock.

Themanagedproviderssupportmoderndatabasefeaturessuchas

connectionpooling.TheOLEDBdataproviderusesOLEDB'sbuilt-in

connectionpooling,whichworksthroughtheclassicCOM+dispenser

manager.TheSQLServerdataproviderusesaninternalpooling

architecturethatbehavessimilarlytoCOM+services'object-pooling

feature.

Thefollowinglistingshowsasimpleconsoleprogramthatconnectstoa

databaseandissuesasimpleselectioncommand.Thisexample

assumesthatSQLServerisinstalledonthemachineandthata

databasenamedCompanyDBisavailable.Theexamplealsoassumes

thatthere'satablenamedEmployeescontainingtheNameandDeptID

columnswithinthedatabase.

//ThisisthemainprojectfileforVC++applicationproject

//generatedusinganApplicationWizard.





#include"stdafx.h"



#using

#using

#using

#include



usingnamespaceSystem;

usingnamespaceSystem::Data;

usingnamespaceSystem::Data::SqlClient;

usingnamespaceSystem::ComponentModel;



//Thisistheentrypointforthisapplication

int_tmain(void)

{

//Createaconnectionobject

SqlConnection*conn;

conn=newSqlConnection

(S"server=localhost;uid=sa;pwd=;database=CompanyDB");



SqlCommand*command;

command=newSqlCommand("select*fromEmployees",conn);

IDataReader*rdr;



try

{

conn->Open();

rdr=command->ExecuteReader();



while(rdr->Read())

{

Console::Write("Name:");

Console::Write(rdr->get_Item("Name"));

Console::Write("Dept:");

Console::WriteLine(rdr->get_Item("DeptID"));

}



}

catch(Exception*e)

{

System::Console::WriteLine(e->ToString());

}

__finally

{

conn->Dispose();

}

return0;

}

NoticethatthecodecreatesaninstanceoftheSqlConnectionclassand

aninstanceoftheSqlCommandclass.Alsonoticethatthecode

initializestheinstanceoftheSqlCommandclasswiththeconnection

objectandasimpleselectionstatement.

Aslongastheconnectionobjectandthecommandobjectworkcorrectly,

youcancreateadatareaderbycallingSqlCommand::ExecuteReader.

Thedatareaderreadsthrougheachrow.Youcanusethedatareader's

get_Itemmethodtofindavaluewithinaspecificcolumnforthatrow.

(We'lldiscussdatareadersindetaillaterinthischapter.)

Theconnectionisopenedandthecommandisexecutedwithinatry

blocktocatchanyerrors.Errorsthatcanoccurinclude:

Invalidconnectionstring(wrongaccountorpasswordorabad

databasename)

Wrongtablename

Wrongcolumnnames

Ifanyerrorsoccurduringtheprocessofconnectingtothedatabaseand

executingthequery,ADO.NETwillthrowanexception.Intheprevious

listing,theexceptioninformationissimplyprintedtothescreen.



IssuingCommands



Connectingtoadatabaseandissuingasimplequeryispretty

straightforward.However,inreal-worldsituations,collectingdataisoften

muchmoreinvolved.Thecommandclasses(SqlCommandand

OleDbCommand)includedwiththemanagedprovidersarefairly

sophisticated.YoucanusethemtosubmitanyvalidSQLaction

statementorquerytothedatabase(oryoucanuseanothercommand

languagesupportedbyanOLEDBprovider).



SqlCommandandOleDbCommandbothimplementtheIDbCommand

interface.Youmightspecifythecommandwhenyouconstructthe

commandobject,oryoumightsetthecommandbyusingthe

CommandTextproperty.Thecommandobjectisassociatedwitha

specificconnectionobject(asshowninthepreviouslisting).The

followinglistingshowshowtoinitializeanSqlCommandfromanexisting

connection.Noticethatthisapproachemphasizesprogrammingtothe

interfacesratherthantotheactualclasses.

IDbConnection*conn=dynamic_cast(newSqlConne

"server=localhost;uid=sa;pwd=;database=CompanyDB"));

IDbCommand*cmd2=newSqlCommand(

"select*fromDepts",

dynamic_cast(conn));

YousawearlierthatIDbCommand::ExecuteReadersubmitsthe

commandandretrievesresultsthroughaDataReaderclass.

IDbCommandalsoincludesamethodnamedExecuteNonQuerythat

returnsonlythenumberofrowsaffected.

Whenapplyingcommandstoacommandobject,anapplicationcanset

theCommandTextpropertytoaSQLcommand(orperhapssomeother

commandlanguagesupportedbyanOLEDBdatabase)orastored

procedurename.TheCommandTypepropertyindicatesthemeaningof

CommandText—whetherit'saplain-textcommandorastored

procedure.



UsingStoredProcedureswithaCommand

Youcanuseacommandobjecttocallstoredprocedurestoperform



databasemanipulation.SqlCommandandOleDbComnandimplement

IDbCommandandsupportparameterizedstatementsthroughthe

Parametersproperty.TheSqlParameterandtheOleDbParameter

classesencapsulatetheparameterfunctionalitynecessaryforstored

procedures.BoththeOleDbCommandandtheSqlCommandinclude

collectionsofparameters—OleDbParameterCollectionand

SqlParameterCollection,respectively.Thefollowinglistingshowshowto

openanSqlConnectionandassociateitwithanSqlCommandthat

executesaparameterizedstoredprocedure.Thislistingexpectsa

databasenamedCompanyDBtobeavailable,whichincludesastored

procedurenamedgetByDeptIDthattakesasinglestringparameter

(designatingthedepartmentID).

voidRunStoredProc()

{

//Executeastoredprocedure

SqlConnection*conn=newSqlConnection(

"server=localhost;uid=sa;pwd=;database=CompanyDB");

SqlCommand*cmd=newSqlCommand("getByDeptID",conn);

IDataReader*reader;



try

{

conn->Open();

cmd->Parameters->Add(

newSqlParameter("@dept_id",SqlDbType::VarChar,11

cmd->Parameters->get_Item("@dept_id")->Value=S"Engine



cmd->CommandType=CommandType::StoredProcedure;

reader=cmd->ExecuteReader();



//Usethereadertoexamineresultset

}



catch(Exception*e)

{

Console::WriteLine(e->ToString());

}



__finally

{

conn->Dispose();

}



}

Asyousetupparameters,youcandesignatethedirectionofeach

parametertobeinput,output,inout,orreturn.Ofcourse,theparameters

yousetupprogrammaticallywillneedtomatchtheformatofthe

parametersintheactualstoredprocedure(althoughstricttypechecking

fortheparametersisn'tenforced).



UsingDataReaderstoRetrieveData

Youcanusedatareaderstoretrieveread-only,forward-onlydata

streams.Asmentioned,afteryoucreateacommandobject,youcancall

IDbCommand::ExecuteReadertocreateadatareaderforretrievingrows

fromadatasource.MostSQLcommandsandstoredprocedures

producerectangularresults.Forexample,whenyouissueSelect*from

Employees,you'reaskingtoseeeverythingwithintheEmployeestable.

Theresultsetyougetbackisacollectionofhomogenousrowsthatyou

canexaminewithanimplementationofIDataReader.Columnswithin

rowscancontainonlyprimitivedatatypes,inaccordancewiththe

relationalmodel.

Earlier,yousawanexampleofusingadatareadertoparsethrougha

resultset.Theexamplegotonlyasingleresultsetback.The

IDataReaderimplementationsinADO.NET(SqlDataReaderand

OleDbDataReader)provideforward-readingaccesstotheresultset.As

youreadthroughtheresultsetusingthereader,thereaderalwayslooks

atthecurrentrow.EachtimeyoucallReadonareader,yougetanew

row.Readreturnsfalsewhentherearenomorerowstoberead.The

datareadersinADO.NETsupportmultipleresultsets.

IDataReader::NextResultadvancesthedatareadertothenextresultset.

Here'sanexampleofgettingmultipleresultsetsbackfromasingle

query:



voidMultipleResultSets()

{

SqlConnection*conn=newSqlConnection(

"server=localhost;uid=sa;pwd=;database=CompanyDB");

SqlCommand*cmd=newSqlCommand(

"select*fromEmployees;select*fromDepts",conn);

IDataReader*rdr;



try

{

conn->Open();

rdr=cmd->ExecuteReader();



boolmore=true;

while(more)

{

while(rdr->Read())

{

Console::Write("Column0=");

//Getthefirstcolumn

Console::WriteLine(rdr->get_Item(0));

//Getthesecondcolumn

Console::Write("Column1=");

Console::WriteLine(rdr->get_Item(1));

}

Console::WriteLine("Endofresultset");

more=rdr->NextResult();

}

}

catch(Exception*e)

{

e->ToString();

}

__finally

{

conn->Dispose();

}



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 35: Programming ADO.NET Using Managed C++

Tải bản đầy đủ ngay(0 tr)

×
x