Вы находитесь на странице: 1из 24

.

NET Best Practices and Coding Standards


Contents Introduction .NET Framework Data Providers Working with DataReaders, DataSets, DataAda ters, and Data!iews "sing #ommands "sing #onnections Integration with $%& %ore "se'u( Ti s

1. Introduction This artic(e rovides )ou with the *est so(utions 'or im (ementing and achieving o tima( (ications, it a(so

er'ormance, sca(a*i(it), and 'unctiona(it) in )our %icroso't AD+.NET a can he( )ou o timi.e the design o' )our AD+.NET a This artic(e contains/

covers *est ractices when using o*-ects avai(a*(e in AD+.NET and o''ers suggestions that (ication.

In'ormation a*out the .NET Framework data roviders inc(uded with the .NET Framework. #om arisons *etween the DataSet and the DataReader, and an e0 (anation o' the *est use 'or each o' these o*-ects. An e0 (anation on how to use the DataSet, Commands, and Connections. In'ormation a*out integrating with $%&. 1enera( ti s and issues. ractices, see.NET Data Access Architecture

For additiona( in'ormation on AD+.NET *est

1uide avai(a*(e in the %SDN &i*rar). Note that the .NET Data Access Architecture 1uide 'ocuses rimari() on architectures that use %icroso't2 S3& Server4 5.6 or (ater. 2. .NET Framework Data Providers A data rovider in the .NET Framework serves as a *ridge *etween an a source. A .NET Framework data (ication and a data

rovider ena*(es )ou to return 7uer) resu(ts 'rom a data

source, e0ecute commands at a data source, and ro agate changes in a DataSet to a data source. This artic(e inc(udes ti s on which .NET Framework data rovider is *est suited 'or )our needs.

Miracle Software Systems

Page 1 of 24

.NET Best Practices and Coding Standards


Which .NET Framework Data Provider to Use? To achieve the *est er'ormance 'or )our a that is most a use in )our a (ications. The 'o((owing ta*(e (ication, use the .NET Framework data rovider rovides in'ormation a*out the avai(a*(e data ro riate 'or.

ro riate 'or )our data source. There are a num*er o' data rovider o tions 'or

roviders and which data sources a data rovider is most a Provider S3& Server Data Provider Details

.NET Found in the System.Data.S lClient names ace. Recommended 'or midd(e8tier a version 5.6 or (ater. (ications using %icroso't S3& Server

Recommended 'or sing(e8tier a (ications using the %icroso't Data Engine 9%SDE: or %icroso't S3& Server 5.6 or (ater. For %icroso't S3& Server version ;.< and ear(ier, )ou must use the +&E D= Provider 'or S3& Server with the +&E D= .NET Data Provider. +&E D= .NET Data Found in the System.Data.!leD" names ace. Provider Recommended 'or midd(e8tier a (ications using %icroso't S3& Server ;.< or ear(ier, or an) +&E D= rovider that su orts the +&E D= inter'aces (isted in +&E D= Inter'aces "sed *) the +&E D= .NET Data Provider in the .NET Framework SD>. 9+&E D= ?.< inter'aces are not re7uired.: For %icroso't S3& Server 5.6 or (ater, the .NET Framework Data Provider 'or S3& Server is recommended. Recommended 'or sing(e8tier a (ications using a %icroso't2 Access data*ase. "se o' an Access data*ase 'or a midd(e8tier a (ication is not recommended. +D=# .NET Provider Data The +D=# .NET Data Provider 'or is avai(a*(e 'or down(oad. Found in the #icroso$t.Data.!d"c names ace. Provides access to data sources that are connected to using an +D=# driver. Note The +D=# .NET Data Provider wi(( *e inc(uded in u coming versions o' the .NET Framework starting with version @.@. The names ace 'or the inc(uded +D=# .NET Data Provider is System.Data.!d"c. .NET Data Provider The %icroso't .NET Data Provider 'or +rac(e is avai(a*(e 'or down(oad. 'or +rac(e

Miracle Software Systems

Page 2 of 24

.NET Best Practices and Coding Standards

Found in the System.Data.!racleClient names ace. Provides access to +rac(e data sources 9version A.@.5 and (ater:. Note The .NET Data Provider 'or +rac(e wi(( *e inc(uded in u coming versions o' the .NET Framework starting with version @.@. #ustom .NET Data AD+.NET rovides a minima( set o' inter'aces to ena*(e )ou to im (ement Provider )our own .NET Framework data rovider. For more in'ormation a*out creating a custom data rovider, see Im (ementing a .NET Data Provider in the .NET Framework SD>. S3&$%& #(asses %anaged The re(ease o' $%& 'or %icroso't S3& Server ?666 9S3&$%& B.6: contains S3&$%& %anaged #(asses that ena*(e )ou to access the $%& 'unctiona(it) o' %icroso't S3& Server ?666 and (ater, 'rom the .NET Framework. For e0am (e, these c(asses ena*(e )ou to e0ecute $%& tem (ates, er'orm $%& Path &anguage 9$Path: 7ueries over data at the server, or er'orm u dates to data using " dategrams or Di''grams. =ui(ding on the 'unctiona(it) 'rom S3&$%& @.6 and ?.6, S3&$%& B.6 introduces We* Services to S3& Server ?666. With S3&$%& B.6, Stored Procedures and $%& Tem (ates can *e e0 osed as a We* Service through S+AP. S3&$%& B.6 is avai(a*(e 'or down(oad.

Connectin% to S&' Server (.) or 'ater For *est er'ormance when connecting to %icroso't S3& Server 5.6 or (ater, use the S3& Server .NET Data Provider. The S3& Server .NET Data Provider is designed to access S3& Server direct() without an) additiona( techno(og) (a)ers. Figure @ i((ustrates the di''erence *etween the various techno(ogies avai(a*(e 'or accessing S3& Server 5.6 or (ater.

Miracle Software Systems

Page 3 of 24

.NET Best Practices and Coding Standards

Fi%*re +. Connectivity methods $or accessin% S&' Server (.) or later

Connectin% to !D,C Data So*rces The +D=# .NET Data Provider, 'ound in the #icroso$t.Data.!d"c names ace, has the same architecture as the .NET data roviders 'or S3& Server and +&E D=. The +D=# .NET Data Provider 9avai(a*(e 'or down(oad:, 'o((ows a naming convention that uses an C+D=#C re'i0 9'or e0am (e !d"cConnection:, and uses standard +D=# connection strings. Note The +D=# .NET Data Provider wi(( *e inc(uded in 'uture versions o' the .NET Framework starting with version @.@. The names ace 'or the inc(uded +D=# .NET Data Provider is System.Data.!d"c. 3. Working with DataReaders Data!ets Data"da#ters and Data$iews AD+.NET rovides two o*-ects 'or retrieving re(ationa( data and storing it in memor)/ the

DataSet and the DataReader. The DataSet rovides an in8memor) re(ationa( re resentation o' data, a com (ete set o' data that inc(udes the ta*(es that contain, order, and constrain the

Miracle Software Systems

Page 4 of 24

.NET Best Practices and Coding Standards


data, as we(( as the re(ationshi s *etween the ta*(es. The DataReader 'orward8on(), read8on() stream o' data 'rom a data*ase. When using a DataSet, )ou wi(( o'ten make use o' a Data-da.ter 9and em (o) a Data/iew to a ossi*() a rovides a 'ast,

Command,*ilder: to interact with )our data source. A(so, when using a DataSet, )ou ma) () sorting and 'i(tering to the data in the DataSet. The DataSet can a(so *e inherited to create a strong() t) ed DataSet in order to e0 ose ta*(es, rows, and co(umns as strong() t) ed o*-ect ro erties. The 'o((owing to ics inc(ude in'ormation on when it is *est to use a DataSet or a DataReader and how to o timi.e access to the data the) contain, as we(( as ti s on how to o timi.e the use o' the Data-da.ter 9inc(uding the Command,*ilder: and Data/iew. DataSet vs. DataReader To determine whether to use the DataSet or the DataReader when )ou design )our a (ication, consider the (eve( o' 'unctiona(it) that is needed in the a (ication/ (ication.

"se the DataSet in order to do the 'o((owing with )our a


Navigate *etween mu(ti (e discrete ta*(es o' resu(ts. %ani u(ate data 'rom mu(ti (e sources 9'or e0am (e, a mi0ture o' data 'rom more than one data*ase, 'rom an $%& 'i(e, and 'rom a s readsheet:. E0change data *etween tiers or using an $%& We* service. "n(ike the DataReader, the DataSet can *e assed to a remote c(ient. Reuse the same set o' rows to achieve a er'ormance gain *) caching them 9such as 'or sorting, searching, or 'i(tering the data:. Per'orm a (arge amount o' rocessing er row. E0tended rocessing on each row returned using a DataReader ties u the connection serving the DataReader (onger than necessar), im acting er'ormance.

%ani u(ate data using $%& o erations such as E0tensi*(e St)(esheet &anguage Trans'ormations 9$S&T trans'ormations: or $Path 7ueries.

"se the DataReader in )our a


(ication i' )ou/

Do not need to cache the data. Are rocessing a set o' resu(ts too (arge to 'it into memor).

Miracle Software Systems

Page 5 of 24

.NET Best Practices and Coding Standards

Need to 7uick() access data once, in a 'orward8on() and read8on() manner.

Note The Data-da.ter uses the DataReader when 'i((ing a DataSet. There'ore, the er'ormance gained *) using the DataReader instead o' the DataSet is that )ou save on the memor) that the DataSet wou(d consume and the c)c(es it takes to o u(ate the DataSet. This er'ormance gain is, 'or the most art, nomina( so )ou shou(d *ase )our design decisions on the 'unctiona(it) re7uired. ,ene$its o$ Usin% a Stron%ly Ty.ed DataSet Another *ene'it o' the DataSet is that it can *e inherited to create a strong() t) ed DataSet. The *ene'its o' a strong() t) ed DataSet inc(ude t) e checking at design time and the advantage o' %icroso't2 !isua( Studio2 .NET statement com (etion 'or )our strong() t) ed DataSet. When )ou have 'i0ed schema or re(ationa( structure 'or )our DataSet, )ou can create a strong() t) ed DataSet that e0 oses rows and co(umns as ro erties o' an o*-ect rather than items in a co((ection. For e0am (e, instead o' e0 osing the name co(umn o' a row 'rom a ta*(e o' customers, )ou e0 ose a C*stomer o*-ectDs Name ro ert). A t) ed DataSet derives 'rom the DataSet c(ass, so that )ou do not sacri'ice an) o' the DataSet 'unctiona(it). That is, a t) ed DataSet can sti(( *e remoted and can *e su (ied as the data source o' a data8*ound contro( such as a Data0rid. I' schema is not known in advance, )ou can sti(( *ene'it 'rom the 'unctiona(it) o' a generic DataSet, *ut )ou 'or'eit the additiona( 'eatures o' a strong() t) ed DataSet. 1andlin% N*lls in a Stron%ly Ty.ed DataSet When using a strong() t) ed DataSet, )ou can annotate the $%& Schema de'inition (anguage 9$SD: schema o' the DataSet to ensure that )our strong() t) ed DataSet a ro riate() hand(es nu(( re'erences. The n*ll/al*e annotation ena*(es )ou to re (ace D,N*ll with a s eci'ied va(ue, Strin%.Em.ty, ersist the nu(( re'erence, or throw an e0ce tion. Which o tion )ou choose de ends on the conte0t o' )our a nu(( re'erence is encountered. (ication. =) de'au(t, an e0ce tion is thrown i' a

Re$reshin% Data in a DataSet I' )ou want to re'resh the va(ues in )our DataSet with u dated va(ues 'rom the server, use Data-da.ter.Fill. I' )ou have rimar) ke)s de'ined on )our DataTa"le, Data-da.ter.Fill

Miracle Software Systems

Page 6 of 24

.NET Best Practices and Coding Standards


matches new rows *ased on the rimar) ke)s, and a (ies the server va(ues as it changes to

the e0isting rows. The RowState o' the re'reshed rows are set to Unchan%ed even i' the) were modi'ied *e'ore the re'resh. Note that, i' no rimar) ke) is de'ined 'or the DataTa"le, Data-da.ter.Fill adds new rows with otentia(() du (icate rimar) ke) va(ues. I' )ou want to re'resh a ta*(e with the current va(ues 'rom the serve whi(e retaining an) changes made to the rows in the ta*(e, )ou must 'irst o u(ate it with Data-da.ter.Fill, 'i(( a new DataTa"le, and then #er%e that DataTa"le into the DataSet with a .reserveChan%es va(ue o' tr*e. Searchin% $or Data in the DataSet When 7uer)ing a DataSet 'or rows that match articu(ar criteria, )ou can increase the

er'ormance o' )our searches *) taking advantage o' inde08*ased (ooku s. When )ou assign a Primary2ey va(ue to a DataTa"le, an inde0 is created. When )ou create a Data/iew 'or a DataTa"le, an inde0 is a(so created. Eere are a 'ew ti s 'or taking advantage o' inde08*ased (ooku s.

I' the 7uer) is against the co(umns that make u the Primary2ey o' the DataTa"le, use DataTa"le.Rows.Find instead o' DataTa"le.Select. For 7ueries invo(ving non8 rimar) ke) co(umns, )ou can im rove er'ormance 'or mu(ti (e 7ueries o' the data using a Data/iew. When )ou a () a sort order to a Data/iew, an inde0 is *ui(t that is used when searching. The Data/iew e0 oses the Find and FindRows methods to 7uer) the data in the under()ing DataTa"le.

I' )ou do not re7uire a sorted view o' a ta*(e, )ou can sti(( take advantage o' inde08*ased (ooku s *) creating a Data/iew 'or the DataTa"le. Note that this is on() an advantage i' )ou are er'orming mu(ti (e 7ueries on the data. I' )ou are on() er'orming a sing(e 7uer), the rocessing re7uired to create the inde0 reduces the er'ormance gained *) using the inde0.

Data/iew Constr*ction The Data/iew *ui(ds an inde0 'or the data in the under()ing DataTa"le when *oth the Data/iew is created, and when the Sort, RowFilter or RowStateFilter ro erties are modi'ied. When creating a Data/iew o*-ect, use the Data/iew constructor that takes the Sort, RowFilter, and RowStateFilter va(ues as constructor arguments 9a(ong with the under()ing DataTa"le:. The resu(t is the inde0 is *ui(t once. #reating an Cem t)C Data/iew

Miracle Software Systems

Page 7 of 24

.NET Best Practices and Coding Standards


and setting the Sort, RowFilter or RowStateFilter ro erties a'terward resu(ts in the inde0 *eing *ui(t at (east twice.

Pa%in% AD+.NET gives )ou e0 (icit contro( over what data is returned 'rom )our data source, as we(( as, how much o' that data is cached (oca(() in a DataSet. There is no sing(e answer 'or aging through a 7uer) resu(t, *ut here are some ti s to consider when designing )our a

(ication.

Avoid the use o' the Data-da.ter.Fill over(oad that takes startRecord and ma3Records va(ues. When 'i((ing a DataSet in this 'ashion, the DataSet is on() 'i((ed with the num*er o' records s eci'ied *) the ma3Records arameter 9starting 'rom the record identi'ied *) the startRecord unnecessar) arameter:, *ut the entire 7uer) is returned regard(ess. This incurs rocessing to read ast the CunwantedC records, as we(( as uses u age o' records at a time is creating a S3&

unnecessar) server resources to return the additiona( records.

A techni7ue used 'or returning on() one

statement that com*ines a WEERE c(ause and an +RDER =F c(ause, with the T+P redicate. This techni7ue re(ies on there *eing a wa) to identi') each row uni7ue(). When navigating to the ne0t age o' records, modi') the WEERE c(ause to inc(ude a(( records where the uni7ue identi'ier is greater than the (ast uni7ue identi'ier o' the current age. When navigating to the revious age o' records, modi') the WEERE c(ause to return a(( the records where the uni7ue identi'ier is (ess than the 'irst uni7ue identi'ier o' the current age. For *oth 7ueries, return on() the T+P age o' records. When navigating to the revious age, )ou need to order the resu(ts in descending order. This wi((, e''ective(), return the *ottom age o' the 7uer) 9)ou wi(( need to reorder the resu(ts *e'ore dis (a)ing them, i' desired:. For an e0am (e o' this techni7ue, see Paging Through a 3uer) Resu(t.

Another techni7ue 'or returning on() one age o' records at a time is to create a S3& statement that com*ines the use o' the T+P redicate and em*edded SE&E#T statements. This techni7ue does not re() on there *eing a wa) to identi') each row uni7ue(). The 'irst ste using this techni7ue is to mu(ti () the age si.e with the num*er o' the desired ages. Fou then ass this num*er to the T+P redicate o' )our S3& 3uer), ordered in ascending order. Fou then em*ed this 7uer) in another 7uer) that se(ects the T+P age8si.e 'rom the em*edded 7uer) resu(ts, ordered in descending order. Essentia((), )ou return the *ottom age o' the em*edded 7uer). For e0am (e, to return the

Miracle Software Systems

Page 8 of 24

.NET Best Practices and Coding Standards


third age o' a 7uer) resu(t where the age si.e is @6, )ou wou(d issue a command (ike the 'o((owing/

SE&E#T T+P @6 G FR+% 9SE&E#T T+P B6 G FR+% #ustomers +RDER =F Id AS#: AS Ta*(e@ +RDER =F Id DES# Note that the age o' resu(ts returned 'rom this 7uer) come in descending order. Fou wi(( need to reorder them i' desired.

I' )our data does not change o'ten, )ou can im rove er'ormance *) maintaining a cache o' records (oca(() in a DataSet. For e0am (e, )ou can store @6 ages worth o' data in a (oca( DataSet, and on() 7uer) the data source 'or new data when the user navigates *e)ond the 'irst or (ast age in the cache.

Fillin% a DataSet with Schema When 'i((ing a DataSet with data, the Data-da.ter.Fill method uses the e0isting schema o' the DataSet and o u(ates it with data returned 'rom the SelectCommand. I' there is no ta*(e name in the DataSet that matches the name o' the ta*(e *eing 'i((ed, the Fill method creates a ta*(e. =) de'au(t, Fill on() de'ines co(umns and co(umn t) es. Fou can override the de'au(t *ehavior o' Fill *) setting the #issin%Schema-ction ro ert) o' the Data-da.ter. For e0am (e, to have Fill create a ta*(e schema that a(so inc(udes rimar) ke) in'ormation, uni7ue constraints, co(umn ro erties, whether nu((s are a((owed, the ma0imum (ength o' the co(umn, read8on() co(umns, and auto8increment co(umns, s eci') that Data-da.ter.#issin%Schema-ction is #issin%Schema-ction.-ddWith2ey. A(ternative(), )ou can ca(( Data-da.ter.FillSchema *e'ore ca((ing Data-da.ter.Fill to ensure that the schema is in (ace when the DataSet is 'i((ed. #a((ing FillSchema wi(( resu(t in an e0tra tri to the server to retrieve the additiona( schema in'ormation. For *est er'ormance, s eci') the schema o' the DataSet, or set the #issin%Schema-ction o' the Data-da.ter *e'ore ca((ing Fill. ,est Practices with the Command,*ilder

Miracle Software Systems

Page 9 of 24

.NET Best Practices and Coding Standards


The Command,*ilder automatica(() generates the 4nsertCommand, U.dateCommand, and DeleteCommand ro erties o' a Data-da.ter *ased on the SelectCommand ro ert) o' the Data-da.ter, rovided that the SelectCommand er'orms a sing(e ta*(e SE&E#T. Eere are some ti s 'or *est er'ormance using the Command,*ilder.

"se o' the Command,*ilder shou(d *e (imited to design time or ad8hoc scenarios. The rocessing re7uired to generate the Data-da.ter command ro erties hinders er'ormance. I' )ou know the contents o' )our INSERTH"PDATEHDE&ETE statements *e'orehand, set them e0 (icit(). A good design ti is to create stored rocedures 'or )our INSERTH"PDATEHDE&ETE commands and e0 (icit() con'igure the Data-da.ter command ro erties to use them.

The Command,*ilder uses the SelectCommand determine the va(ues 'or the other command command ro erties.

ro ert) o' the Data-da.ter to

ro erties. I' the SelectCommand o' the

Data-da.ter itse(' is ever changed, *e sure to ca(( Re$reshSchema to u date the

The Command,*ilder on() generates a command 'or a Data-da.ter command ro ert) i' that command ro ert) is nu(( 9the command ro erties are nu(( *) de'au(t:. I' )ou e0 (icit() set a command ro ert), the Command,*ilder does not overwrite it. I' )ou want the Command,*ilder to generate a command 'or a command ro ert) that has *een set revious(), set the command ro ert) to nu((.

,atch S&' Statements %an) data*ases su ort com*ining, or *atching, mu(ti (e commands together in a sing(e

command e0ecution. For e0am (e, S3& Server ena*(es )ou to se arate commands using a semi co(on 9,:. #om*ining mu(ti (e commands into a sing(e command reduces the num*er o' tri s made to the server and can im rove the er'ormance o' )our a e0am (e, store u a(( the intended de(etes (oca(() in )our a command ca(( to de(ete them 'rom the data source. Though this does im rove er'ormance, it ma) increase the com (e0it) o' )our a create a Data-da.ter 'or each DataTa"le in )our DataSet. Fillin% a DataSet with #*lti.le Ta"les (ication (ication. Fou can, 'or (ication, and then issue one *atch

when managing u dates to data in the DataSet. To maintain sim (icit), )ou ma) want to

Miracle Software Systems

Page 10 of 24

.NET Best Practices and Coding Standards


I' )ou use a *atch S3& statement to retrieve mu(ti (e ta*(es and 'i(( a DataSet, the 'irst ta*(e is named using the ta*(e name s eci'ied to the Fill method. Su*se7uent ta*(es are named using the name s eci'ied to the Fill method (us a num*er starting 'rom one and incrementing *) one. For e0am (e, i' )ou were to run the 'o((owing code/ 5/is*al ,asic Dim da As S7(DataAda ter I New S7(DataAda ter9CSE&E#T G FR+% #ustomers, SE&E#T G FR+% +rders,C, m)#onnection: Dim ds As DataSet I New DataSet9: da.Fi((9ds, C#ustomersC: 66C7 S7(DataAda ter da I new S7(DataAda ter9CSE&E#T G FR+% #ustomers, SE&E#T G FR+% +rders,C, m)#onnection:, DataSet ds I new DataSet9:, da.Fi((9ds, C#ustomersC:, The data 'rom the #ustomers ta*(e is (aced in a DataTa"le named C#ustomersC. The data 'rom the +rders ta*(e is (aced in a DataTa"le named C#ustomers@C. Fou can easi() modi') the Ta"leName ro ert) o' the C#ustomers@C ta*(e to *e C+rdersC a'ter the DataSet has *een 'i((ed. Eowever, su*se7uent 'i((s wou(d resu(t in the C#ustomersC ta*(e *eing re8'i((ed, *ut the C+rdersC ta*(e *eing ignored and another C#ustomers@C ta*(e *eing created. To remed) this situation, create a DataTa"le#a..in% that ma s C#ustomers@C to C+rdersC and additiona( ta*(e ma 5/is*al ,asic Dim da As S7(DataAda ter I New S7(DataAda ter9CSE&E#T G FR+% #ustomers, SE&E#T G FR+% +rders,C, m)#onnection: da.Ta*(e%a ings.Add9C#ustomers@C, C+rdersC: Dim ds As DataSet I New DataSet9: da.Fi((9ds, C#ustomersC: 66C7 S7(DataAda ter da I new S7(DataAda ter9CSE&E#T G FR+% #ustomers, SE&E#T G FR+% +rders,C, m)#onnection:, ings 'or other su*se7uent ta*(es. For e0am (e/

Miracle Software Systems

Page 11 of 24

.NET Best Practices and Coding Standards


da.Ta*(e%a ings.Add9C#ustomers@C, C+rdersC:,

DataSet ds I new DataSet9:, da.Fi((9ds, C#ustomersC:, Usin% the DataReader The 'o((owing are some ti s 'or *est er'ormance using a DataReader, as we(( as, answers to common 7uestions regarding the use o' the DataReader.

The DataReader must *e c(osed *e'ore accessing an) out ut associated Command.

arameters 'or the

A(wa)s c(ose the DataReader when )ou are 'inished reading the data. I' the Connection )ou are using is on() used to return the DataReader, c(ose it immediate() a'ter c(osing the DataReader. An a(ternative to e0 (icit() c(osing the Connection is to ass

Command,ehavior.CloseConnection to the E3ec*teReader method to ensure that the associated connection is c(osed when the DataReader is c(osed. This is es ecia(() use'u( i' )ou are returning a DataReader 'rom a method and do not have contro( over the c(osing o' the DataReader or associated connection.

The DataReader cannot *e remoted *etween tiers. The DataReader is designed 'or connected data access. When accessing co(umn data use the t) ed accessors (ike 0etStrin%, 0et4nt89, and so on. This saves )ou the rocessing re7uired to cast the !":ect returned 'rom 0et/al*e as a articu(ar t) e.

+n() one DataReader can *e o en at a time, o'' o' a sing(e connection. In AD+, i' )ou o ened a sing(e connection and re7uested two recordsets that used a 'orward8on(), read8 on() cursor, AD+ im (icit() o ens a second, un oo(ed connection to the data store 'or the (i'e o' that cursor, and then im (icit() c(oses it. With AD+.NET, (itt(e is done 'or )ou Cunder8 the8coversC. I' )ou want two DataReaders o en at the same time, o'' the same data store, )ou have to e0 (icit() create two connections, one 'or each DataReader. This is one wa) that AD+.NET gives )ou more contro( over the use o' oo(ed connections.

=) de'au(t, the DataReader (oads an entire row into memor) with each Read. This a((ows 'or random access o' co(umns within the current row. I' this random access is not necessar), 'or increased er'ormance, ass Command,ehavior.Se *ential-ccess to the ca(( to E3ec*teReader. This changes the de'au(t *ehavior o' the DataReader to on()

Miracle Software Systems

Page 12 of 24

.NET Best Practices and Coding Standards


(oad data into memor) when it is re7uested. Note that,

Command,ehavior.Se *ential-ccess re7uires )ou to access returned co(umns in order. That is, once )ou have read ast a returned co(umn, )ou can no (onger read its va(ue.

I' )ou are 'inished reading the data 'rom a DataReader, *ut sti(( have a (arge num*er o' unread resu(ts ending, ca(( Cancel on the Command rior to ca((ing Close on the DataReader. #a((ing Close on the DataReader causes it to retrieve ending resu(ts and em t) the stream rior to c(osing the cursor. #a((ing Cancel on the Command discards resu(ts on the server so that the DataReader does not have to read though them when it is c(osed. I' )ou are returning out ut arameters 'rom )our Command, ca((ing Cancel discards them as we((. I' )ou need to read an) out ut arameters, do not ca(( Cancel on the Command, -ust ca(( Close on the DataReader.

,inary 'ar%e !":ects ;,'!,s< When using the DataReader to retrieve a =inar) &arge +*-ect 9=&+=:, )ou shou(d ass

Command,ehavior.Se *ential-ccess to the E3ec*teReader method ca((. =ecause the de'au(t *ehavior o' the DataReader is to (oad an entire row into memor) with each Read, and *ecause =&+= va(ues can *e ver) (arge, the resu(t can *e (arge amounts o' memor) *eing used u 'or a sing(e =&+=. Se *ential-ccess sets the *ehavior o' the DataReader to on() (oad the data re7uested. Fou can then contro( how much data is (oaded at a time using 0et,ytes or 0etChars. Remem*er that, when using Se *ential-ccess, )ou cannot access the di''erent 'ie(ds returned *) the DataReader out o' order. That is, i' )our 7uer) returns three co(umns, the third o' which is a =&+=, and )ou want to access data in the 'irst two co(umns, )ou must access the 'irst co(umn va(ue, then the second co(umn va(ue *e'ore accessing the =&+= data. This is *ecause the data is now returned in se7uence and is not avai(a*(e once the DataReader has read ast it. For a detai(ed descri tion o' how to access a =&+= in AD+.NET, see +*taining =&+= !a(ues 'rom a Data*ase.

Miracle Software Systems

Page 13 of 24

.NET Best Practices and Coding Standards


%. &sing 'ommands AD+.NET rovides severa( di''erent methods 'or command e0ecution, as we(( as di''erent

o tions 'or o timi.ing the e0ecution o' a command. The 'o((owing inc(udes ti s on choosing the *est command e0ecution and how to im rove the er'ormance o' an e0ecuted command. ,est Practices with !leD"Command #ommand e0ecution *etween the di''erent .NET Framework data roviders is standardi.ed as much as ossi*(e. Eowever, there are di''erences *etween the data roviders. The 'o((owing are some ti s 'or 'ine8tuning command e0ecution with the .NET Framework Data Provider 'or +&E D=.

"se CommandTy.e.Te3t with the +D=# #A&& s)nta0 to ca(( stored rocedures. "sing CommandTy.e.StoredProced*re -ust generates the +D=# #A&& s)nta0 under the covers.

=e sure to set the !leD"Parameter t) e, si.e 9i' a

(ica*(e:, as we(( as recision and () the

sca(e 9i' the arameter is o' t) e numeric or decima(:. Note that, i' )ou do not su accessor with ever) command e0ecution. ,est Practices with S lCommand A 7uick ti stored 'or e0ecuting stored

arameter in'ormation e0 (icit(), the !leD"Command recreates the +&E D= arameter

rocedures using the S lCommand/ I' )ou are ca((ing a arse the command *e'ore

rocedure, s eci') a CommandTy.e o' StoredProced*re 'or the CommandTy.e

ro ert) o' the S lCommand. This removes the need to e0ecution, *) e0 (icit() identi')ing it as a stored rocedure. Use o$ the Pre.are #ethod

The Command.Pre.are method can im rove the er'ormance o' arameteri.ed commands that are re eated at )our data source. Pre.are instructs the data source to o timi.e the s eci'ied command 'or mu(ti (e ca((s. To use Pre.are e''ective(), )ou need to thorough() understand how )our data source res onds to the Pre.are ca((. For some data sources such as S3& Server ?666, commands are im (icit() o timi.ed and a ca(( to Pre.are is unnecessar). For other data sources such as S3& Server 5.6, Pre.are can *e e''ective. S.eci$y Schema and #etadata E3.licitly

Miracle Software Systems

Page 14 of 24

.NET Best Practices and Coding Standards


%an) o*-ects in AD+.NET in'er metadata in'ormation whenever the user does not s eci') it. E0am (es are/
The Data-da.ter.Fill method, which creates a ta*(e and co(umns in a DataSet i' none

e0ist
The Command,*ilder, which generates Data-da.ter command

ro erties 'or sing(e8 Command o*-ectDs

ta*(e SE&E#T commands.


Command,*ilder.DeriveParameters,

which

o u(ates

Parameters co((ection. Each time these 'eatures are used, however, there is a er'ormance hit. It is recommended that these 'eatures *e used rimari() 'or design8time and ad8hoc a (ications. Whenever ossi*(e, s eci') the schema and metadata e0 (icit(). This inc(udes de'ining ta*(es and co(umns in a DataSet, de'ining the Command Parameter in'ormation 'or a Command. E3ec*teScalar and E3ec*teNon&*ery I' )ou want to return a sing(e va(ue such as the resu(t o' #ount9G:, Sum9Price:, or Avg93uantit):, )ou can use Command.E3ec*teScalar. E3ec*teScalar returns the va(ue o' the 'irst co(umn o' the 'irst row, returning resu(t set as a sca(ar va(ue. E3ec*teScalar *oth sim (i'ies )our code and im roves er'ormance *) accom (ishing in a sing(e ste , what wou(d have *een a two8ste rocess using a DataReader 9that is, E3ec*teReader J 1et the va(ue:. ro erties o' a Data-da.ter, and de'ining

When using S3& statements that do not return rows, (ike those that modi') data 9such as INSERT, "PDATE, or DE&ETE: or return on() out ut E3ec*teNon&*ery. This removes an) unnecessar) DataReader. Testin% $or N*ll I' a co(umn in a ta*(e 9in )our data*ase: a((ows nu((s, )ou cannot test 'or a arameter va(ue o' Ce7ua( toC nu((. Instead, )ou need to write a WEERE c(ause to test whether *oth the co(umn is nu(( and the arameter is nu((. The 'o((owing S3& statement returns rows where the &astName co(umn e7ua(s the va(ue assigned to the K&astName &astName co(umn and the K&astName arameter are nu((. arameter, or whether *oth the arameters or return va(ues, use rocessing to create an em t)

Miracle Software Systems

Page 15 of 24

.NET Best Practices and Coding Standards


SE&E#T G FR+% #ustomers WEERE 99&astName I K&astName: +R 9&astName IS N"&& AND K&astName IS N"&&:: Passin% N*ll as a Parameter /al*e When sending a nu(( va(ue as a Parameter va(ue in a command to the data*ase, )ou cannot use n*ll 9Nothin% in !isua( =asic2 .NET:. Instead )ou need to use D,N*ll./al*e. For e0am (e/ 5/is*al ,asic Dim aram As S7(Parameter I New S7(Parameter9CKNameC, S7(D*T) e.N!ar#har, ?6: aram.!a(ue I D=Nu((.!a(ue 66C7 S7(Parameter aram I new S7(Parameter9CKNameC, S7(D*T) e.N!ar#har, ?6:, aram.!a(ue I D=Nu((.!a(ue, Per$ormin% Transactions The transaction mode( has changed 'or AD+.NET. In AD+, when StartTransaction was ca((ed, an) u date 'o((owing the ca(( is considered that needs to *e associated with the Transaction ena*(es )ou to art o' the transaction. Eowever, in ro ert) o' a Command. This design AD+.NET, when Connection.,e%inTransaction is ca((ed, a Transaction o*-ect is returned er'orm mu(ti (e root transactions o'' o' a sing(e connection. I' the

Command.Transaction ro ert) is not set to a Transaction that has *een started 'or the associated Connection, the Command 'ai(s and an e0ce tion is thrown. " coming re(eases o' the .NET Framework wi(( ena*(e )ou to manua(() en(ist in an e0isting distri*uted transaction. This is idea( 'or an o*-ect oo(ing scenario where a connection is o ened once 'or a oo(ed o*-ect, *ut the o*-ect is invo(ved in mu(ti (e se arate transactions. This ca a*i(it) is not avai(a*(e in the .NET Framework @.6 re(ease. (. &sing 'onnections Eigh er'ormance a (ications kee connections to the data source in use 'or a minima( er'ormance enhancing techno(og) such as )ou achieve greater rovide )ou with ti s to he(

amount o' time, as we(( as take advantage o' connection oo(ing. The 'o((owing to ics

er'ormance when using AD+.NET to connect to )our data source. Connection Poolin%

Miracle Software Systems

Page 16 of 24

.NET Best Practices and Coding Standards


The S3& Server, +&E D=, and .NET Framework Data Provider 'or +D=# oo( connections im (icit(). Fou can contro( connection8 oo(ing *ehavior *) s eci')ing di''erent attri*ute va(ues in the connection string. For detai(s on how to contro( connection +&E D= .NET Data Provider. !.timi=in% Connections with the Data-da.ter The Fill and U.date methods, o' the Data-da.ter, automatica(() o en the connection s eci'ied 'or the re(ated command ro ert) i' it is c(osed. I' the Fill or U.date method o en the connection, Fill or U.date wi(( c(ose it when the o eration is com (ete. For *est er'ormance, kee connections to the data*ase o en on() when re7uired. A(so, reduce the num*er o' times )ou o en and c(ose a connection 'or mu(ti (e o erations. It is recommended that, i' )ou are on() er'orming a sing(e Fill or U.date method ca((, that )ou a((ow the Fill or U.date method to o en and c(ose the connection im (icit(). I' )ou are making numerous ca((s to Fill andHor U.date, it is recommended that )ou e0 (icit() o en the connection, make )our ca((s to Fill andHor U.date, and then e0 (icit() c(ose the connection. Additiona((), when er'orming transactions, e0 (icit() o en the connection *e'ore *eginning oo(ing *ehavior, see #onnection Poo(ing 'or the S3& Server .NET Data Provider and #onnection Poo(ing 'or the

the transaction and c(ose the connection a'ter )ou commit. For e0am (e/ 5/is*al ,asic Pu*(ic Su* RunS7(Transaction9da As S7(DataAda ter, m)#onnection As S7(#onnection, ds As DataSet: m)#onnection.+ en9: Dim m)Trans As S7(Transaction I m)#onnection.=eginTransaction9: m)#ommand.Transaction I m)Trans Tr) da." date9ds: m)Trans.#ommit9: #onso(e.Write&ine9C" date success'u(.C: #atch e As E0ce tion Tr) m)Trans.Ro((*ack9: #atch e0 As S7(E0ce tion

Miracle Software Systems

Page 17 of 24

.NET Best Practices and Coding Standards


I' Not m)Trans.#onnection Is Nothing Then #onso(e.Write&ine9CAn e0ce tion o' t) e C L e0.1etT) e9:.ToString9: L M C was encountered whi(e attem ting to ro(( *ack the transaction.C: End I' End Tr) #onso(e.Write&ine9CAn e0ce tion o' t) e C L e.1etT) e9:.ToString9: L C was encountered.C: #onso(e.Write&ine9C" date 'ai(ed.C: End Tr) m)#onnection.#(ose9: End Su* 66C7 u*(ic void RunS7(Transaction9S7(DataAda ter da, S7(#onnection m)#onnection, DataSet ds: N m)#onnection.+ en9:, S7(Transaction m)Trans I m)#onnection.=eginTransaction9:, m)#ommand.Transaction I m)Trans, tr) N da." date9ds:, m)#ommand.Transaction.#ommit9:, #onso(e.Write&ine9C" date success'u(.C:, O catch9E0ce tion e: N tr) N m)Trans.Ro((*ack9:, O catch 9S7(E0ce tion e0: N i' 9m)Trans.#onnection PI nu((: N

Miracle Software Systems

Page 18 of 24

.NET Best Practices and Coding Standards


#onso(e.Write&ine9CAn e0ce tion o' t) e C J e0.1etT) e9: J C was encountered whi(e attem ting to ro(( *ack the transaction.C:, O O #onso(e.Write&ine9e.ToString9::, #onso(e.Write&ine9C" date 'ai(ed.C:, O m)#onnection.#(ose9:, O -lways Close Connections and DataReaders A(wa)s e0 (icit() c(ose )our Connection or DataReader o*-ects when )ou are 'inished using them. Whi(e gar*age co((ection eventua(() c(eans u o*-ects and there'ore re(eases connections and other managed resources, gar*age co((ection on() occurs when it is needed. There'ore, it is sti(( )our res onsi*i(it) to make sure an) e0 ensive resources are e0 (icit() re(eased. A(so, Connections that are not e0 (icit() c(osed might not *e returned to the oo(. For e0am (e, a connection that has gone out o' sco e *ut that has not *een e0 (icit() c(osed wi(( on() *e returned to the connection oo( i' the ma0imum oo( si.e has *een reached and the connection is sti(( va(id. Note Do not ca(( Close or Dis.ose on a Connection, a DataReader, or an) other managed o*-ect in the Finali=e method o' )our c(ass. In a 'ina(i.er, on() re(ease unmanaged resources that )our c(ass owns direct(). I' )our c(ass does not own an) unmanaged resources, do not inc(ude a Finali=e method in )our c(ass de'inition.

Use the >Usin%> Statement in C7 For #Q rogrammers, a convenient wa) to ensure that )ou a(wa)s c(ose )our Connection and DataReader o*-ects is to use the *sin% statement. The *sin% statement automatica(() ca((s Dis.ose on the o*-ect *eing CusedC when (eaving the sco e o' the *sin% statement. For e0am (e/ 66C7 string connString I CData SourceI(oca(host,Integrated Securit)ISSPI,Initia( #ata(ogINorthwind,C,

Miracle Software Systems

Page 19 of 24

.NET Best Practices and Coding Standards


using 9S7(#onnection conn I new S7(#onnection9connString:: N S7(#ommand cmd I conn.#reate#ommand9:, cmd.#ommandTe0t I CSE&E#T #ustomerId, #om an)Name FR+% #ustomersC, conn.+ en9:, using 9S7(DataReader dr I cmd.E0ecuteReader9:: N whi(e 9dr.Read9:: #onso(e.Write&ine9CN6ORtN@OC, dr.1etString96:, dr.1etString9@::, O O The using statement is not avai(a*(e 'or %icroso't2 !isua( =asic2 .NET. -void -ccessin% the !leD"Connection.State Pro.erty I' the connection has *een o ened, !leD"Connection.State ro ert) makes the native +&E D= ca(( 4D,Pro.erties.0etPro.erties to the D-T-S!URCE4NF! D,PR!P?C!NNECT4!NST-TUS source. In other words, checking the State ro ert) set 'or the to the data (ication ma) ro ert), which ma) resu(t in a round tri

ro ert) can *e e0 ensive. So on() check the

State ro ert) when re7uired. I' )ou need to check this ro ert) o'ten, )our a on the StateChan%e event, see Working with #onnection Events. ). Integration with *+,

er'orm *etter i' )ou (isten 'or the StateChan%e event 'or )our !leD"Connection. For detai(s

AD+.NET rovides e0tensive $%& integration in the DataSet, and a(so e0 oses some o' the $%& 'unctiona(it) rovided *) S3& Server ?666 and (ater. Fou can a(so make use o' S3&$%& B.6 'or e0tensive access to the $%& 'unctiona(it) in S3& Server ?666 and (ater. Eere are ti s and in'ormation when using $%& and AD+.NET. The DataSet and @#' The DataSet is tight() integrated with $%& roviding )ou with the a*i(it) to/

&oad the schema or re(ationa( structure o' a DataSet 'rom $SD Schema.

Miracle Software Systems

Page 20 of 24

.NET Best Practices and Coding Standards


&oad the contents o' a DataSet 'rom $%&. In'er the schema o' a DataSet 'rom the contents o' an $%& document when no schema is su (ied. Write the schema o' a DataSet as $SD Schema. Write the contents o' a DataSet as $%&. Eave s)nchronous access to *oth the re(ationa( re resentation o' )our data using the DataSet, as we(( as the hierarchica( re resentation o' )our data using the @mlDataDoc*ment.

Note Fou can use this s)nchroni.ation to a

() $%& 'unctiona(it) such as $Path 7ueries and

$S&T trans'ormations to the data in )our DataSet, or to rovide a re(ationa( view o' a((, or a su*set o' the data in an $%& document whi(e reserving the 'ide(it) o' the origina( $%&. For detai(ed in'ormation on the $%& 'unctiona(it) rovided with the DataSet, see $%& and the DataSet. Schema 4n$erence When (oading a DataSet 'rom an $%& 'i(e, )ou can (oad the schema o' the DataSet 'rom $SD Schema, or )ou can rede'ine the ta*(es and co(umns *e'ore (oading the data. I' no $SD Schema is avai(a*(e and )ou do not know which ta*(es and co(umns to de'ine 'or the contents o' an $%& 'i(e, )ou can in'er the schema *ased on the structure o' the $%& document. Schema in'erence is use'u( as a migration too(, *ut shou(d *e (imited to design8time a

(ications on() as the in'erence rocess has the 'o((owing (imitations. In'erring schema introduces additiona( a (ication. A(( in'erred co(umns are o' t) e string. The in'erence rocess is not deterministic. That is, it is *ased on the contents o' the $%& 'i(e, not the intended schema. As a resu(t, )ou can have two $%& 'i(es, with the same intended schema, that resu(t in two entire() di''erent in'erred schemas *ecause their contents di''er. rocessing that hinders the er'ormance o' an

S&' Server F!R @#' &*eries

Miracle Software Systems

Page 21 of 24

.NET Best Practices and Coding Standards


I' )ou are returning the resu(ts o' a S3& Server ?666 F+R $%& 7uer), )ou can have the .NET Framework Data Provider 'or S3& Server direct() create an @mlReader using the S lCommand.E3ec*te@mlReader method. S&'@#' #ana%ed Classes There are c(asses avai(a*(e that e0 ose the 'unctiona(it) o' $%& 'or S3& Server ?666 in the .NET Framework. These c(asses are 'ound in the #icroso$t.Data.S l@ml names ace and add the a*i(it) to e0ecute $Path 7ueries and $%& Tem (ate 'i(es, as we(( as a trans'ormation to data. S3&$%& %anaged #(asses are inc(uded in the re(ease o' $%& 'or %icroso't S3& Server ?666 9S3&$%& ?.6:, which is avai(a*(e at $%& 'or %icroso't S3& Server ?666 We* Re(ease ? 9S3&$%& ?.6:. -. +ore &se.u/ Ti#s Eere are some genera( ti s 'or writing AD+.NET code. -voidin% -*toA4ncrement /al*e Con$licts &ike most data sources, the DataSet ena*(es )ou to identi') co(umns that automatica(() increment their va(ue when new rows are added. When using auto8increment co(umns in a DataSet, with auto8increment co(umns 'rom a data source, avoid con'(icts *etween the (oca( num*ering o' rows added to the DataSet and rows added to the data source. For e0am (e, consider a ta*(e with an auto8incrementing rimar) ke) co(umn o' #ustomerID. Two new rows o' customer in'ormation are added to the ta*(e and receive auto8incremented #ustomerID va(ues o' @ and ?. Then, on() the second customer row is assed to the U.date method o' the Data-da.ter, the new() added row receives an auto8incremented #ustomerID va(ue o' @ at the data source, which does not match the va(ue ?, in the DataSet. When the Data-da.ter 'i((s the second row in the ta*(e with the returned va(ue, a constraint vio(ation occurs *ecause the 'irst customer row a(read) has a #ustomerID o' @. To avoid this *ehavior, it is recommended that, when working with auto8incrementing co(umns at a data source and auto8incrementing co(umns in a DataSet, )ou create the co(umn in the DataSet with an -*to4ncrementSte. o' 8@ and an -*to4ncrementSeed o' 6, as we(( as ensuring that )our data source generates auto8incrementing identit) va(ues starting 'rom @ () $S&T

Miracle Software Systems

Page 22 of 24

.NET Best Practices and Coding Standards


and incrementing with a ositive ste va(ue. As a resu(t, the DataSet generates negative ositive auto8increment

num*ers 'or auto8incremented va(ues that do not con'(ict with the

va(ues generated *) the data source. Another o tion is to use co(umns o' t) e 0*id instead o' auto8incrementing co(umns. The a(gorithm that generates 0*id va(ues shou(d never generate the same 0*id in the DataSet as is generated *) the data source. I' )our auto8incremented co(umn is used sim () as a uni7ue va(ue, and does not have an) meaning, consider using 1uids instead o' auto8incrementing co(umns. The) are uni7ue and avoid the e0tra work necessar) to work with auto8incremented co(umns. For an e0am (e o' retrieving auto8increment co(umn va(ues 'rom a data source, see Retrieving Identit) or AutoNum*er !a(ues. Check $or !.timistic Conc*rrency /iolations =ecause the DataSet is, *) design, disconnected 'rom the data source, )ou need to ensure that )our a (ication avoids con'(icts when mu(ti (e c(ients u date data at the data source, according to the o timistic concurrenc) mode(. There are severa( techni7ues when testing 'or an o timistic concurrenc) vio(ation. +ne invo(ves inc(uding a timestam co(umn in the ta*(e. Another techni7ue is to veri') that a(( the origina( co(umn va(ues in a row sti(( match those 'ound in the data*ase *) testing using a WEERE c(ause in )our S3& statement. For a detai(ed discussion on this to ic inc(uding a code e0am (e, see + timistic #oncurrenc). #*ltithreaded Pro%rammin% AD+.NET is o timi.ed 'or er'ormance, through ut, and sca(a*i(it). As a resu(t, the AD+.NET o*-ects do not (ock resources and must on() *e used on a sing(e thread. The one e0ce tion is the DataSet, which is thread8sa'e 'or mu(ti (e readers. Eowever, )ou need to (ock the DataSet during writes. -ccess -D! *sin% C!# 4ntero. !nly When Re *ired AD+.NET is designed to *e the *est so(ution 'or a (arge num*er o' a some a AD+ %u(tidimensiona( 9AD+%D:. In these situations, the a (ications. Eowever,

(ications re7uire ca a*i(ities that are on() avai(a*(e using AD+ o*-ects, 'or e0am (e (ication can access AD+ using

#+% Intero . Note that using #+% Intero to access data with AD+ incurs a er'ormance hit.

Miracle Software Systems

Page 23 of 24

.NET Best Practices and Coding Standards


When designing an a (ication, 'irst determine i' AD+.NET meets )our design needs *e'ore

im (ementing a design that accesses AD+ using #+% Intero .

Miracle Software Systems

Page 24 of 24

Вам также может понравиться