Sie sind auf Seite 1von 25

Implementing a Generic Data Access Layer in ADO.

NET Part 1 A Data Access Layer (DAL) is an integral part in the design of any application. There are plenty of articles that discuss how we an implement a DAL using ADO.NET. Most of these ha e constraints in the sense that they are not generic in nature. !n other words" they are not pro ider independent. This series of articles will discuss the implementation of a generic" i.e." a pro ider independent Data Access Layer in ADO.NET. The #asic prere$uisite to learning this article is a proper understanding of ADO.NET and good coding s%ills in &'. ! will present the code e(amples in this article in &'. )owe er with little effort" you can twist it o er to *+.NET as well. The ,trategies !n ol ed Let us first understand what the necessities are for #uilding such a layer. ! would rather start #y discussing how an application designed using ADO.NET actually connects to the data#ase and performs the &-.D (&reate" -ead" .pdate and Delete) operations. /irst" you need to open the connection using a data#ase pro ider. /ine" #ut what is a pro ider anyway0 A pro ider is responsi#le for connecting to a specific data#ase. 1hy specific0 The reason is that a pro ider for an Oracle data#ase cannot #e used to connect to a ,2L ,er er data#ase and ice3 ersa. Ne(t" you need a command o#4ect that can #e used to e(ecute the data#ase commands of your choice. This is followed #y the usage of a Data-eader or a Data,et or a DataTa#le instance to retrie e data (if you are performing a -ead operation) from the data#ase ta#le. 1hen you use a Data,et" you need a DataAdapter as a #ridge #etween the actual data#ase and the Data,et instance. !mplementing the DAL /ramewor% 1ith this in mind" let us design a pro ider independent Data Access Layer. Let us first understand the ADO.NET Li#rary. The ma4or classes that constitute the ADO.NET li#rary are5 &onnection &ommand Data -eader Data Adapter The corresponding interfaces that the a#o e classes implement are stated #elow. !D+&onnection !Data-eader !D+&ommand !D+DataAdapter The Data 6ro iders that ma%e up the li#rary are specific to a particular data#ase that they would connect to. These are the Data 6ro iders that are a aila#le in ADO.NET. ,2L ,er er Data 6ro ider Oracle Data 6ro ider OD+& Data 6ro ider OleD+ Data 6ro ider Now we are all set to implement our DAL. The ma4or components that constitute our DAL #loc% are5 6ro iderType (Enum) Data#ase&onnection,tate (Enum) ,tored6rocedure6arameterDirection (Enum) D+Manager (&lass) D+)elper (&lass) 1e will start our discussion with the enum data type that would contain the data pro ider types in it. These pro ider types relate to the data#ases that we will #e connecting to" depending our re$uirements. The following code snippet illustrates the 6ro iderType enum that contains four alues that correspond to a specific data pro ider. pu#lic enum 6ro iderType 7 ,$l,er er" OleD#" Oracle" OD+&" &onfigDefined

8 Now" there may #e situations where you might need to either %eep the data#ase connection state open or close after a data#ase operation is o er. As an e(ample" after you read data into a Data-eader instance from the underlying data#ase" you might need to %eep the connection state open for su#se$uent operations. 9ou may also need to close it if it is no longer used. :eeping this in mind" let us ha e an enum data type that houses two alues that correspond to the data#ase connection states that we 4ust discussed a#out. The following is the code for the enum called Data#ase&onnection,tate. pu#lic enum Data#ase&onnection,tate 7 :eepOpen" &loseOnE(it 8 1hen you are e(ecuting the stored procedures" you might want to send data to the data#ase or retrie e the same from the data#ase. Accordingly" we ha e another enum called ,tored6rocedure6arameterDirection that contains alues that correspond to the parameter directions for the stored procedures that we would e(ecute with the help of our DAL. The following is the code for this enum.

public enum StoredProcedureParameterDirection { Input, InputOutput, Output, ReturnValue }


1e need a factory class that would return a D#6ro ider/actory type instance or a D#DataAdapter type instance depending on the data pro ider that we are using. This class contains factory methods that typically are static methods. 1hat is a static method" anyway0 This is an often misunderstood concept #ut a ery important one. 1ell" a static method" often called a shared method (it is shared #y all instances of the class that it #elongs to) #elongs to the class and a non3static method #elongs to an o#4ect of a class. That is" a non3static method can only #e called on an o#4ect of a class that it #elongs to. A static method can howe er #e called #oth on the class as well as an o#4ect of the class. /urther" a static method can access the static mem#ers of a class only unli%e a non3static method that can access #oth static and non3static mem#ers. These static methods in the D+/actory class accept a reference to the 6ro iderType enum that denotes the data pro ider type in use. The ne(t class in our discussion is the D+/actory class" designed on the factory design pattern. +efore we discuss the D+/actory class and its intent" let us understand what a factory design pattern is. 1hat is a factory design pattern0 The /actory pattern is responsi#le for pro iding an interface for the creation of o#4ects" #ut allows the inherited classes to decide on the appropriate time of these instantiations. The following is the source code for our D+/actory class. !t contains two static methods called ;et6ro ider and ;etDataAdapter #oth of which accept an instance of the data#ase pro ider type enum" i.e." 6ro iderType. using ,ystem.Data.&ommon<

using using using using using using {

System.Data.SqlClient System.Data.OleDb System.Data.Odbc System.Data.OracleClient System.Collections.!eneric System."e#t

namespace DataAccessLayer

internal class D$%actory

{ pri&ate static DbPro&ider%actory ob'%actory ( null


pu#lic static D#6ro ider/actory ;et6ro ider(6ro iderType pro ider)

{ s)itc* +pro&ider, { case Pro&ider"ype.SqlSer&erob'%actory ( SqlClient%actory.Instance brea. case Pro&ider"ype.OleDbob'%actory ( OleDb%actory.Instance brea. case Pro&ider"ype.Oracleob'%actory ( OracleClient%actory.Instance brea. case Pro&ider"ype.OD$Cob'%actory ( Odbc%actory.Instance brea. } return ob'%actory
pu#lic static D#DataAdapter ;etDataAdapter(6ro iderType pro iderType) 7 switch (pro iderType) 7 case 6ro iderType.,$l,er er5 return new ,$lDataAdapter()< case 6ro iderType.OleD#5 return new OleD#DataAdapter()< case 6ro iderType.OD+&5 return new Od#cDataAdapter()< case 6ro iderType.Oracle5 return new OracleDataAdapter()< default5 return null< 8 8

8 8

Note that you ha e different pro iders for different data#ases" i.e." the data#ase pro iders are all data#ase specific. A DataAdapter as we may recall" is a #ridge #etween the data#ase and the Data,et = a set of disconnected data. Though you ha e arious data readers depending on the type of the data pro ider you are using" you ha e only one type of data set. 1hy0 This is #ecause a data set is a disconnected in3memory set of data. The schema of the data#ase defines the schema of the data set. -efer to the code e(ample shown a#o e. +oth the methods in the code e(ample shown a#o e chec% the alue of the enum reference instance and accordingly return an appropriate D#Data6ro ider or D#6ro ider/actory instance respecti ely. ,uch methods are actually called factory methods. &onclusion !n this article we ha e discussed how we can design and implement and generic data access layer" i.e." one that can #e used to perform data#ase operations irrespecti e of the data#ase #eing used. !n

the ne(t article in this series" we will discuss the Data#asehelper class" i.e." the class that actually performs the data#ase operations. Implementing a Generic Data Access Layer in ADO.NET Part 2 !n the first part of this series of articles on Data Access Layer" we ha e had a loo% at what the strategies are" for designing and implementing a ;eneric Data Access Layer. 1e ha e had a loo% at the enumerators and the factory classes that we will #e using. !n this part of this article of three part series" we will discuss how we can implement the Data#ase)elper class" one that would #e responsi#le for performing the actual data#ase operations. The Data#ase)elper class encapsulates the arious calls to the data#ase to perform the &-.D operations. The D+Manager class that we will discuss later acts as a wrapper on top of this class. 9ou ha e arious methods in the Data#ase)elper class to add parameters" to e(ecute $ueries" stored procedures" etc. )ere is the code that illustrates how the connection to the data#ase is esta#lished #ased on the pro ider type chosen and the command o#4ect created.

public Database/elper+string connectionstring, Pro&ider"ype pro&ider, { t*is.strConnectionString ( connectionstring ob'%actory ( D$%actory.!etPro&ider+pro&ider, ob'Connection ( ob'%actory.CreateConnection+, ob'Command ( ob'%actory.CreateCommand+, ob'Connection.ConnectionString ( t*is.strConnectionString ob'Command.Connection ( ob'Connection }

!n ADO.NET" you ha e the following data pro iders. ,2L ,er er Data 6ro ider Oracle Data 6ro ider Od#c Data 6ro ider OleD+ Data 6ro ider Note5 Depending on the data pro ider used" you need to use the command o#4ect that is specific to that pro ider. 9our data reader should also #e specific to the data pro ider used. The use of the D+/actory class as shown in the code snippet a#o e. Note that you use the command o#4ects to e(ecute the data#ase commands that contain the ,2L statements. Added to this" we will ha e o erloaded ersions of Add6arameter method to add parameters to the command o#4ects so that we can pass parameters to the data#ase stored procedures or ,2L statements. )ere is the simplest ersion of the Add6arameter method.

internal int 0ddParameter+string name, ob'ect &alue, { DbParameter dbParameter ( ob'%actory.CreateParameter+, dbParameter.Parameter1ame ( name dbParameter.Value ( &alue return ob'Command.Parameters.0dd+dbParameter, }
1hile the 6arameterName identifies the uni$ue name of the parameter to #e passed" the *alue implies the alue of the parameter passed. )ence" if the 6arameterName comprises of >?EmpName@" the

6arameterAs alue might #e >Boydip :an4ilal@. !n order to ensure that our DataAccessLayer supports transactions" we ha e three methods that ena#le support for transactions. /ine" #ut what is a transaction0 A transaction is an unit of wor% that is guaranteed to #e e(ecuted in its entirety or not e(ecuted at all. )ere are those methods.

internal &oid $egin"ransaction+, { i2 +ob'Connection.State (( System.Data.ConnectionState.Closed, { ob'Connection.Open+, }


o#4&ommand.Transaction C o#4&onnection.+eginTransaction()< internal oid &ommitTransaction()

} {

ob'Command."ransaction.Commit+, ob'Connection.Close+, }
internal oid -oll#ac%Transaction()

{ ob'Command."ransaction.Rollbac.+, ob'Connection.Close+, }
Note that we ha e methods that correspond to #eginning" commiting or rolling a transaction #ac% to re ert the changes. 1e will ha e the following four methods for performing the &-.D (&reate" .pdate" -ead and Delete) operations in the data#ase. These methods are5 E(ecute,calar() E(ecute-eader() E(ecuteNon2uery() E(ecuteData,et() The E(ecute,calar() method is used to read one alue from the data#ase. The E(ecute-eader() method returns a Data-eader instance from the data#ase populated with rows of data. The E(ecuteNon2uery() method is used to insert" update or delete data either using ,2L statements or using stored procedures. The following is the complete code for the Data#ase)elper class.

using using using using using using using using using using

System System.Collections.!eneric System."e#t System.Data System.Con2iguration System.Data.Common System.Data.SqlClient System.Data.OleDb System.Data.Odbc System.IO

using Application/ramewor%.&onfiguration<

namespace Application/ramewor%.DataAccessLayer

{ public class Database/elper - IDisposable { pri&ate string strConnectionString pri&ate DbConnection ob'Connection pri&ate DbCommand ob'Command pri&ate DbPro&ider%actory ob'%actory ( null pri&ate ParameterCac*e parameterCac*e ( ParameterCac*e.!etParameterCac*e+,
pu#lic Data#ase)elper(string connectionstring" 6ro iderType pro ider)

{ t*is.strConnectionString ( connectionstring ob'%actory ( D$%actory.!etPro&ider+pro&ider, ob'Connection ( ob'%actory.CreateConnection+, ob'Command ( ob'%actory.CreateCommand+, ob'Connection.ConnectionString ( t*is.strConnectionString ob'Command.Connection ( ob'Connection } internal int 0ddParameter+string name, ob'ect &alue, { DbParameter dbParameter ( ob'%actory.CreateParameter+, dbParameter.Parameter1ame ( name dbParameter.Value ( &alue return ob'Command.Parameters.0dd+dbParameter, }
internal int Add6arameter(D#6arameter parameter)

{ return ob'Command.Parameters.0dd+parameter,
internal int Add6arameter(string name" ,tored6rocedure6arameterDirection parameterDirection)

} {

DbParameter parameter ( ob'%actory.CreateParameter+,


parameter.6arameterName C name<

switch (parameterDirection)

parameter.Value ( String.3mpty parameter.Db"ype ( Db"ype.String parameter.Si4e ( 56 {

case StoredProcedureParameterDirection.Inputparameter.Direction ( System.Data.ParameterDirection.Input brea. case StoredProcedureParameterDirection.Outputparameter.Direction (

System.Data.ParameterDirection.Output brea. case StoredProcedureParameterDirection.InputOutputparameter.Direction ( System.Data.ParameterDirection.InputOutput brea. case StoredProcedureParameterDirection.ReturnValueparameter.Direction ( System.Data.ParameterDirection.ReturnValue brea. }
return o#4&ommand.6arameters.Add(parameter)< internal int Add6arameter(string name" o#4ect alue" ,tored6rocedure6arameterDirection parameterDirection)

} {

parameter.6arameterName C name<

DbParameter parameter ( ob'%actory.CreateParameter+, parameter.Value ( &alue parameter.Db"ype ( Db"ype.String parameter.Si4e ( 56

switch (parameterDirection)

{ case StoredProcedureParameterDirection.Inputparameter.Direction ( System.Data.ParameterDirection.Input brea. case StoredProcedureParameterDirection.Outputparameter.Direction ( System.Data.ParameterDirection.Output brea. case StoredProcedureParameterDirection.InputOutputparameter.Direction ( System.Data.ParameterDirection.InputOutput brea. case StoredProcedureParameterDirection.ReturnValueparameter.Direction ( System.Data.ParameterDirection.ReturnValue brea. }
return o#4&ommand.6arameters.Add(parameter)<

}
internal int Add6arameter(string name" ,tored6rocedure6arameterDirection parameterDirection" int siDe" D#Type d#Type)

{ DbParameter parameter ( ob'%actory.CreateParameter+,

parameter.6arameterName C name<

switch (parameterDirection)

parameter.Db"ype ( db"ype parameter.Si4e ( si4e {

case StoredProcedureParameterDirection.Inputparameter.Direction ( System.Data.ParameterDirection.Input brea. case StoredProcedureParameterDirection.Outputparameter.Direction ( System.Data.ParameterDirection.Output brea. case StoredProcedureParameterDirection.InputOutputparameter.Direction ( System.Data.ParameterDirection.InputOutput brea. case StoredProcedureParameterDirection.ReturnValueparameter.Direction ( System.Data.ParameterDirection.ReturnValue brea. }
return o#4&ommand.6arameters.Add(parameter)< internal int Add6arameter(string name" o#4ect alue" ,tored6rocedure6arameterDirection parameterDirection" int siDe" D#Type d#Type)

} {

parameter.6arameterName C name<

DbParameter parameter ( ob'%actory.CreateParameter+, parameter.Value ( &alue parameter.Db"ype ( db"ype parameter.Si4e ( si4e

switch (parameterDirection)

{ case StoredProcedureParameterDirection.Inputparameter.Direction ( System.Data.ParameterDirection.Input brea. case StoredProcedureParameterDirection.Outputparameter.Direction ( System.Data.ParameterDirection.Output brea. case StoredProcedureParameterDirection.InputOutputparameter.Direction ( System.Data.ParameterDirection.InputOutput brea.

case StoredProcedureParameterDirection.ReturnValueparameter.Direction ( System.Data.ParameterDirection.ReturnValue brea. }


return o#4&ommand.6arameters.Add(parameter)< internal D#&ommand &ommand

} {

get { return ob'Command } }


internal D#&onnection &onnection

{ get { return ob'Connection }


internal oid +eginTransaction()

} {

i2 +ob'Connection.State (( System.Data.ConnectionState.Closed, { ob'Connection.Open+, }


o#4&ommand.Transaction C o#4&onnection.+eginTransaction()< internal oid &ommitTransaction()

} {

ob'Command."ransaction.Commit+, ob'Connection.Close+, }
internal oid -oll#ac%Transaction()

{ ob'Command."ransaction.Rollbac.+, ob'Connection.Close+,
internal int E(ecuteNon2uery(string $uery)

} {

return 3#ecute1on7uery+query, Command"ype."e#t, DatabaseConnectionState.CloseOn3#it, }


internal int E(ecuteNon2uery(string $uery" &ommandType commandtype)

{ return 3#ecute1on7uery+query, commandtype,

DatabaseConnectionState.CloseOn3#it, }
internal int E(ecuteNon2uery(string $uery" Data#ase&onnection,tate connectionstate)

{ return 3#ecute1on7uery+query, Command"ype."e#t, connectionstate, }


internal int E(ecuteNon2uery(string $uery" &ommandType commandtype" Data#ase&onnection,tate connectionstate)

{
int i C 3E< try

ob'Command.Command"e#t ( query ob'Command.Command"ype ( commandtype {

i2 +ob'Connection.State (( System.Data.ConnectionState.Closed, { ob'Connection.Open+, }


i C o#4&ommand.E(ecuteNon2uery()<

} catc* { t*ro) } 2inally { i2 +connectionstate (( DatabaseConnectionState.CloseOn3#it, { ob'Connection.Close+, } }


return i< internal o#4ect E(ecute,calar(string $uery)

} {

return 3#ecuteScalar+query, Command"ype."e#t, DatabaseConnectionState.CloseOn3#it, }


internal o#4ect E(ecute,calar(string $uery" &ommandType commandtype)

{ return 3#ecuteScalar+query, commandtype, DatabaseConnectionState.CloseOn3#it, } { return 3#ecuteScalar+query, Command"ype."e#t,

internal o#4ect E(ecute,calar(string $uery" Data#ase&onnection,tate connectionstate)

connectionstate, }
internal o#4ect E(ecute,calar(string $uery" &ommandType commandtype" Data#ase&onnection,tate connectionstate)

{ ob'Command.Command"e#t ( query ob'Command.Command"ype ( commandtype ob'ect o ( null try { i2 +ob'Connection.State (( System.Data.ConnectionState.Closed, { ob'Connection.Open+, }
o C o#4&ommand.E(ecute,calar()<

} catc* { t*ro) } 2inally { ob'Command.Parameters.Clear+, i2 +connectionstate (( DatabaseConnectionState.CloseOn3#it, { ob'Connection.Close+, } }


return o<

}
internal D#Data-eader E(ecute-eader(string $uery)

{ return 3#ecuteReader+query, Command"ype."e#t, DatabaseConnectionState.CloseOn3#it, }


internal D#Data-eader E(ecute-eader(string $uery" &ommandType commandtype)

{ return 3#ecuteReader+query, commandtype, DatabaseConnectionState.CloseOn3#it, }


internal D#Data-eader E(ecute-eader(string $uery" Data#ase&onnection,tate connectionstate)

{ return 3#ecuteReader+query, Command"ype."e#t, connectionstate, }


internal D#Data-eader E(ecute-eader(string $uery" &ommandType commandtype" Data#ase&onnection,tate connectionstate)

{ ob'Command.Command"e#t ( query ob'Command.Command"ype ( commandtype DbDataReader reader ( null try { i2 +ob'Connection.State (( System.Data.ConnectionState.Closed, { ob'Connection.Open+, } i2 +connectionstate (( DatabaseConnectionState.CloseOn3#it, { reader ( ob'Command.3#ecuteReader+Command$e*a&ior.CloseConnection, } else { reader ( ob'Command.3#ecuteReader+, }
8

catc* { } 2inally { ob'Command.Parameters.Clear+, }

return reader<

}
internal Data,et E(ecuteData,et(string $uery)

{ return 3#ecuteDataSet+query, Command"ype."e#t, DatabaseConnectionState.CloseOn3#it, }


internal Data,et E(ecuteData,et(string $uery" &ommandType commandtype)

{ return 3#ecuteDataSet+query, commandtype, DatabaseConnectionState.CloseOn3#it, }


internal Data,et E(ecuteData,et(string $uery" Data#ase&onnection,tate connectionstate)

{ return 3#ecuteDataSet+query, Command"ype."e#t, connectionstate, }


internal Data,et E(ecuteData,et(string $uery" &ommandType commandtype" Data#ase&onnection,tate connectionstate)

{ DbData0dapter adapter ( ob'%actory.CreateData0dapter+, ob'Command.Command"e#t ( query ob'Command.Command"ype ( commandtype adapter.SelectCommand ( ob'Command DataSet ds ( ne) DataSet+, try { adapter.%ill+ds, } catc* { t*ro) } 2inally { ob'Command.Parameters.Clear+, i2 +connectionstate (( DatabaseConnectionState.CloseOn3#it, { i2 +ob'Connection.State (( System.Data.ConnectionState.Open, { ob'Connection.Close+, } } } return ds }
pu#lic oid Dispose()

{ i2 +ob'Connection.State (( ConnectionState.Open, { ob'Connection.Close+, ob'Connection.Dispose+, }

o#4&ommand.Dispose()<

}
internal !Data-eader E(ecute-eader(string stored6rocedureName" params o#4ectFG parameters)

{ ob'Command.Command"e#t ( storedProcedure1ame ob'Command.Command"ype ( Command"ype.StoredProcedure DbDataReader reader ( null try { Retrie&eParameters+ob'Command, SetParameterValues+ob'Command, parameters,

if (o#4&onnection.,tate CC ,ystem.Data.&onnection,tate.&losed)

{ ob'Connection.Open+, } reader ( ob'Command.3#ecuteReader+, } catc* { t*ro) } 2inally { ob'Command.Parameters.Clear+, } return reader


internal oid ,et6arameter*alues(D#&ommand o#4&ommand" o#4ectFG parameters)

} {

int inde# ( 6 2or +int i ( 6 i 8 parameters.9engt* i::, { DbParameter parameter ( ob'Command.Parameters;i : inde#< SetParameterValue+ob'Command, parameter.Parameter1ame, parameters;i<, } } { dbCommand.Parameters;parameter1ame<.Value ( +&alue (( null, = D$1ull.Value - &alue }
internal oid -etrie e6arameters(D#&ommand d#&ommand)

internal irtual oid ,et6arameter*alue(D#&ommand d#&ommand" string parameterName" o#4ect alue)

{ i2 +parameterCac*e.ContainsParameters+Connection.ConnectionString, dbCommand.Command"e#t,, { DbParameter;< parameters ( parameterCac*e.!etParameters+Connection.ConnectionString, dbCommand.Command"e#t, dbCommand.Parameters.0ddRange+parameters, } else {

string connectionString ( Connection.ConnectionString dbCommand.Connection ( Connection Connection.Open+, SqlCommand$uilder.Deri&eParameters+dbCommand as SqlCommand, parameterCac*e.0ddParameters+connectionString, dbCommand.Command"e#t, dbCommand.Parameters, } }
internal o#4ect ;et6arameter(string name)

{ return ob'Command.Parameters;name<.Value } } }
&onclusion !n the concluding part of this series we will discuss how we can create a wrapper class that encapsulates the D+)elper class and how we can use that class to perform the arious &-.D operations in our data#ase.

Implementing a Generic Data Access Layer in ADO.NET Part 3 !n this the final article of this series" ! will discuss the other classes in this framewor% and how we can use this framewor% to perform arious &-.D operations in our applications. Let us start from where we left off in the pre ious part of this series. Note that most of the methods of the Data#ase)elper class ha e #een mar%ed as >internal@ to pre ent them from #eing called outside of the >Application/ramewor%.DataAccessLayer@ namespace. Now we will come to the D+Manager class< the wrapper class that encapsulates the calls to another class called D+)elper that actually performs the &-.D operations on the underlying data#ase. The D+Manager class e(tends the D+Manager+ase a#stract class. The D+Manager+ase class contains the definition for the Open () and the &lose () methods and some other pu#lic properties that are generic and can #e used #y any class that acts as a wrapper. 1e will ha e a loo% at the D+Manager+ase class first. The following code listing shows the D+Manager+ase class.

using using using using using using using using using using {

System System.Collections.!eneric System."e#t System.Data System.Con2iguration System.Data.Common System.Data.SqlClient System.Data.OleDb System.Data.Odbc System.IO

namespace Application/ramewor%.DataAccessLayer

public abstract class D$>anager$ase { protected Database/elper database/elper ( null protected DbDataReader dbDataReader ( null protected DataSet dataSet ( null protected Pro&ider"ype pro&ider"ype protected String connectionString ( String.3mpty protected bool isOpen ( 2alse
pu#lic #ool !sOpen

{ get { return isOpen


set

} { isOpen ( &alue } }

pu#lic string &onnection,tring

{ get { return connectionString


set

} { connectionString ( &alue } }

pu#lic D#&onnection &onnection

{ get { return database/elper.Connection }


pu#lic D#&ommand &ommand

} {

get { return database/elper.Command } }


pu#lic 6ro iderType D+6ro ider

{ set {

pro&ider"ype ( &alue }
get

{ return pro&ider"ype }
pu#lic Data,et D+,et

} {

get { return dataSet } }


pu#lic D#Data-eader D+-eader

{ get { return dbDataReader }


protected oid Open(string connection,tring)

} {

database/elper ( ne) Database/elper+connectionString, D$Pro&ider, }


protected oid &lose()

{ i2 +dbDataReader ?( null, i2 +?dbDataReader.IsClosed, dbDataReader.Close+, database/elper.Dispose+,


pu#lic oid +eginTransaction()

} {

database/elper.$egin"ransaction+, }
pu#lic oid &ommitTransaction()

{ database/elper.Commit"ransaction+,
pu#lic oid -oll#ac%Transaction()

} {

database/elper.Rollbac."ransaction+, } } }
Note that the D+Manager+ase class contains the most common methods that are re$uired. 9ou can Open or &lose a connection" +egin" &ommit or -oll#ac% transactions" etc. These methods would

remain the same and are mandatory in this conte(t e en if you decide to ha e another ersion of the D+Manager class with some more methods implemented it. The D+Manager class that e(tends the D+Manager+ase a#stract class contains a list of methods that can #e used to e(ecute stored procedures" $ueries and return Data,et instance or Data-eader instances as well. 9ou can opt for %eeping your connection open after the E(ecute-eader method is called so that you can use the li e connection in the su#se$uent operations that you need to perform on your data#ase. The methods names in the D+Manager class relate to the operations that they are meant to perform. ! feel not you will ha e any pro#lems understanding what each of these methods are supposed to do. Then" you ha e the Add6arameter method that can #e used to add parameters to your stored procedure so that at the time of in o%ing the procedure" you can pass the parameters along. The connection string that we need to use to connect to our data#ase can #e set using the &onnection,tring pu#lic property. The connection string can typically #e stored in your configuration file and the D+Manager class can read the configuration file to retrie e the connection string. The pro ider type can #e set using the 6ro iderType enum. /ine" #ut" where will these alues #e set" i.e." how can we call the D+Manager and from where0 &onfused0 )ang on. Let us ha e a loo% at the D+Manager class followed #y how we can use this class to perform &-.D operations. The following code listing depicts the D+Manager class.

using using using using using using using using using using {

namespace Application/ramewor%.DataAccessLayer

System System.Collections.!eneric System."e#t System.Data System.Con2iguration System.Data.Common System.Data.SqlClient System.Data.OleDb System.Data.Odbc System.IO

public sealed class D$>anager - D$>anager$ase { public &oid OpenConnection+, { connectionString ( Con2igurationSettings.0ppSettings;@ConnectionString@<."oString+, base.Open+connectionString, }
pu#lic oid Open&onnection(,tring connection,tring)

{ base.Open+connectionString, base.IsOpen ( true


pu#lic oid &lose&onnection()

} {

i2 +base.isOpen, base.Close+,

base.IsOpen ( 2alse }
pu#lic int Add6arameter(string name" o#4ect alue)

{ return database/elper.0ddParameter+name, &alue,


pu#lic int Add6arameter(string name" ,tored6rocedure6arameterDirection parameterDirection)

} {

return database/elper.0ddParameter+name, parameterDirection, }


pu#lic int Add6arameter(string name" o#4ect alue" ,tored6rocedure6arameterDirection parameterDirection)

{ return database/elper.0ddParameter+name, &alue, parameterDirection, } public int 0ddParameter+string name, StoredProcedureParameterDirection parameterDirection, int si4e, Db"ype db"ype, { return database/elper.0ddParameter+name, parameterDirection, si4e, db"ype, } public int 0ddParameter+string name, ob'ect &alue, StoredProcedureParameterDirection parameterDirection, int si4e, Db"ype db"ype, { return database/elper.0ddParameter+name, &alue, parameterDirection, si4e, db"ype, } public ob'ect !etParameter+string name, { return database/elper.!etParameter+name, } public DbDataReader 3#ecuteReader+string query, { t*is.dbDataReader ( database/elper.3#ecuteReader+query, return t*is.dbDataReader } public DbDataReader 3#ecuteReader+string query, Command"ype commandtype, { t*is.dbDataReader ( database/elper.3#ecuteReader+query, commandtype, DatabaseConnectionState.CloseOn3#it, return t*is.dbDataReader

} public IDataReader 3#ecuteReader+string storedProcedure1ame, params ob'ect;< parameters, { t*is.dbDataReader ( +DbDataReader,database/elper.3#ecuteReader+storedProcedure1ame, parameters, return t*is.dbDataReader } public DbDataReader 3#ecuteReader+string query, Command"ype commandtype, DatabaseConnectionState connectionstate, { t*is.dbDataReader ( database/elper.3#ecuteReader+query, commandtype, connectionstate, return t*is.dbDataReader } public DbDataReader 3#ecuteReader+string query, DatabaseConnectionState connectionstate, { t*is.dbDataReader ( database/elper.3#ecuteReader+query, connectionstate, return t*is.dbDataReader } public ob'ect 3#ecuteScalar+string query, { return database/elper.3#ecuteScalar+query, } public ob'ect 3#ecuteScalar+string query, Command"ype commandtype, { return database/elper.3#ecuteScalar+query, commandtype, } public ob'ect 3#ecuteScalar+string query, DatabaseConnectionState connectionstate, { return database/elper.3#ecuteScalar+query, connectionstate, } public ob'ect 3#ecuteScalar+string query, Command"ype commandtype, DatabaseConnectionState connectionstate, { return database/elper.3#ecuteScalar+query, commandtype, connectionstate, } public DataSet 3#ecuteDataSet+string query,

{ t*is.dataSet ( database/elper.3#ecuteDataSet+query, return t*is.dataSet } public DataSet 3#ecuteDataSet+string query, Command"ype commandtype, { t*is.dataSet ( database/elper.3#ecuteDataSet+query, commandtype, return t*is.dataSet } public int 3#ecute1on7uery+string query, Command"ype commandtype, { return database/elper.3#ecute1on7uery+query, commandtype, } public int 3#ecute1on7uery+string query, Command"ype commandtype, DatabaseConnectionState databaseConnectionState, { return database/elper.3#ecute1on7uery+query, commandtype, databaseConnectionState, } } }
.sing the D+Manager class 9ou can ma%e use of the D+Manager class as shown in the code snippet #elow. D+Manager d#Manager C new D+Manager()<

db>anager.OpenConnection+, db>anager.3#ecuteReader+@Select A 2rom employee@, )*ile +db>anager.D$Reader.Read+,, Response.Brite+db>anager.D$Reader;C3mp1ameD<."oString+,, db>anager.CloseConnection+,

Note that the Open&onnection and the &lose&onnection methods of the D+Manager class in o%e the Open and the &lose methods of the D+Manager+ase class internally. ,imilarly" you can use the D+Manager class to insert data as shown in the code snippet #elow.

D$>anager db>anager ( ne) D$>anager+, String sql ( @insert into employee +3mpCode, 3mp1ame, &alues +E366FEEGoydipE,@ try { db>anager.OpenConnection+, db>anager.3#ecute1on7uery+sql,Command"ype."e#t, } catc*+3#ception e, {

/ttpConte#t.Current.Response.Brite+e, }
finally

{ db>anager.CloseConnection+, /ttpConte#t.Current.Response.Brite+@8$RH@:@F record added...@, } New Features in A P.NET 3.!


A,6.NET has for long #een a popular we# application de elopment platform. A,6.NET H.I added a lot of new features compared to its earlier counterpart" i.e." A,6.NET E.E. 1ith A,6.NET J.K" you ha e e en more features. This article will present the new features that ha e #een added to A,6.NET and *isual ,tudio HIIL. /ine" #ut" whatAs new0 !n A,6.NET J.K" a new tool has #een introduced called the A,6.NET Merge Tool. 9ou can use this tool for merging pre3compiled assem#lies. No" this is not all. There isa lot of other e(citing features and we will e(plore each of them as we progress through this article. The most significant impro ements in A,6.NET are5 !ntegrated A4a( ,upport New Data &ontrols (List*iew and Data6ager) The Lin$Data,ource &ontrol *isual ,tudio HIIL has also included some features for an impro ed we# application de elopment e(perience. )ere is the list of such impro ements5 ,upport for L!N2 !ntelli,ense for Ba a,cript and A,6.NET A4a( !mpro ed Design time e(perience 1e will e(plore each of these features as we progress through this article. New A,6.NET /eatures 1e will start our discussion with the impro ements in A,6.NET. The sections that follow discuss the significant impro ements made in A,6.NET J.K. !ntegrated A4a( ,upport +efore we proceed further" let us ha e a $uic% loo% at what A4a( is all a#out. A4a(" an acronym for Asynchronous Ba a,cript and MML" is a cross3platform technology that can #e used to ma%e your we# pages fast" rich and responsi e. Note that in A4a( ena#led we# applications" re$uests are sent to the ser er only for the data that is needed. !ncidentally" A4a( is mainly a mi( of Ba ascript" )tml" &,," MML" DOM and the MML)ttp-e$uest O#4ect. !t is a technology that can #e used to send and recei e data (usually in MML format) from a ser er3side application using Ba ascript. According to Enrich 6eterson" NABAM3ena#led pages pro ide a slic%" responsi e user e(perience" ma%ing we#3#ased applications function more li%e des%top3#ased onesN. M,DN states" NA,6.NET ABAM is a set of technologies to add ABAM (Asynchronous Ba a,cript and MML) support to A,6.NET. !t consists of a client3side script framewor%" ser er controls" and more. Although ABAM is essentially a client3side techni$ue" most of its real3world deployments call for ser er3side processing.N )ere is a list of the ad antages of using A4a( in we# applications. -eduction of unnecessary we# ser er hits" i.e." the round trips are minimiDed -ich" responsi e user interface -eal3time we# page updates Language neutrality

/aster we# page renderings Less consumption of ser erAs resources (memory and processor load is reduced) A4a( was introduced in A,6.NET as a separate add3on called A,6.NET H.I ABAM E(tensions. This e(tensions li#rary ena#led you to design and implement A4a( ena#led we# applications using A,6.NET. The A,6.NET H.I framewor% incorporates the client script li#raries of the A,6.NET A4a( framewor%. NThe framewor% includes two distinct yet not mutually e(clusi e A6!Os5 client and ser er" which ena#le the de elopers to accomplish ABAM functionalities using direct client3side programming" traditional ser er3side programming" or any com#ination of #othN. And" you also ha e the A,6.NET ABAM &ontrol Tool%it" a community pro4ect from Microsoft that comprises of a ,D: and code samples. According to Microsoft" NThe A,6.NET ABAM &ontrol Tool%it pro ides a set of sample controls and e(tenders that ma%es it a snap to spice up your we# site with rich functionalityN. !n A,6.NET J.K" you also ha e support for the A,6.NET ser er side application ser ices li%e" Authentication" Mem#ership" -oles Management" 6rofiles" etc" e(posed as we# ser ices. 9ou can call these ser ices from client side scripts seamlessly. 1ith A,6.NET J.K" you ha e #uilt in support for creating ABAM ena#led we# pages for A,6.NET. 9ou can also create A,MM P 1&/ #ased we# ser ices and consume them using the Microsoft ABAM Li#rary. New Data &ontrols (List*iew and Data6ager) A,6.NET J.K includes two new data controls" namely" List*iew and Data6ager. The new and impro ed List*iew control included as part of A,6.NET J.K support all &-.D (&reate" -ead" .pdate" Delete) operations. !t also supports paging and sorting of data. 9ou can use the new Data6ager control to implement paging functionality to your data controls seamlessly. 9ou can find more information on how to use these data controls in my latest #oo% titled" A,6.NET Data 6resentation &ontrols Essentials (6ac%t 6u#lishing). !n my #oo%" ! ha e discussed how to #ind data to these new data controls introduced in A,6.NET J.K using L!N2. The Lin$Data,ource &ontrol The Lin$Data,ource &ontrol ena#les de elopers to declarati ely #ind data to A,6.NET data controls #y e(ecuting L!N2 $ueries against the data stores. The L!N2Data,ource &ontrol can also #e used to e(ecute stored procedures and comple( $ueries. !t can #e used to #ind data to a wide ariety of data sources li%e" custom #usiness o#4ects" collections or data#ases. ,cott ;uthrie says" NOne of the #enefits of using the Qasp5lin$datasourceR control is that it le erages the fle(i#ility that L!N2 #ased O-Ms pro ide. 9ou donOt need to define custom $uerySinsertSupdateSdelete methods for the data source to call 3 instead you can point the Qasp5lin$datasourceR control at your data model" identify what entity ta#le you want it to wor% against" and then #ind any A,6.NET .! control against the Qasp5lin$datasourceR and ha e them wor% with it.N -eference5 http5SSwe#logs.asp.netSscottguSarchi eSHIITSITSEUSlin$3to3s$l3part3K3#inding3ui3using3the3asp3 lin$datasource3control.asp(LetAs LetAs dig into some code again. )ere is how the L!N2Data,ource &ontrol can #e declared.

8asp-9inqDataSource Conte#t"ype1ame(@SalesDataConte#t@ "able1ame(@Sales@ ID(@SalesDataSource@ runat(@ser&er@H 8Iasp-9inqDataSourceH


And" here is the mar%3up code of a ;rid*iew &ontrol that illustrates how you can use the L!N2Data,ource &ontrol shown a#o e to #ind data.

8asp-!ridVie)

DataSourceID(@SalesDataSource@ 0uto!enerateColumns(@2alse@ ID(@!ridVie)F@ runat(@ser&er@H 8ColumnsH 8asp-$ound%ield Data%ield(@SalesCode@ IH 8asp-$ound%ield Data%ield(@SalesDate@ IH 8asp-$ound%ield Data%ield(@Sales7uantity@ IH 8asp-$ound%ield Data%ield(@SalesPrice@ IH 8asp-$ound%ield Data%ield(@Salesman1ame@ IH 8IColumnsH 8Iasp-!ridVie)H
New *isual ,tudio HIIL /eatures The most e(citing thing that ! o#ser ed in *isual ,tudio HIIL is that you can write your code that targets any one of the following ersions of .NET /ramewor%. Microsoft .NET H.I Microsoft .NET J.I Microsoft .NET J.K And" most importantly" *isual ,tudio will automatically filter the intellisense" the items in the Add -eference dialog #o( and the controls in the tool#o( to show only the features that the ersion in use supports. AwesomeV !snOt it0 No" this is not all. There are some other new and e(citing features too. -ead on. ,upport for Language !ntegrated 2uery (L!N2) Language !ntegrated 2uery or L!N2 comes with Microsoft .NET /ramewor% J.I and e(tends the $uery synta( of &' and *+.NET to allow the de elopers to $uery data without ha ing to write data store specific code. LetAs dig into some code" right0 )ere is a sample code snippet that illustrates how you can $uery data using L!N2.

9ist8stringH students ( 2rom s in Student>aster )*ere s.StudentCode ( F6FF select s.Student1ame


According to M,DN" NLanguage3!ntegrated 2uery (L!N2) is a set of features in *isual ,tudio HIIL that e(tends powerful $uery capa#ilities to the language synta( of &' and *isual +asic. L!N2 introduces standard" easily3learned patterns for $uerying and updating data" and the technology can #e e(tended to support potentially any %ind of data store.N -eference5 http5SSmsdnH.microsoft.comSen3 usSli#raryS##JWTWHU.asp(!mpro ed !mpro ed Design time e(perience 1ith *isual ,tudio HIIL" you ha e a much impro ed designer and impro ed &,, editing options. 9ou ha e a code along side design model 3 a new split screen feature where you can see the design of your we# page as you write your mar%3up code. !n other words" you get a 19,!19; display of your we# page as you add content to the mar%3up of your we# page. !ntelli,ense for Ba a,cript and A,6.NET A4a( Apart from this" you ha e the much awaited Ba ascript intellisense feature = one that the de elopers were in waiting for long. This includes intellisense support for #oth in3line Ba ascript code as well as e(ternal Ba ascript files referred in your code.

&onclusion A,6.NET J.K and *isual ,tudio HIIL promises to deli er impro ed fle(i#ility and de eloper e(perience. ,cott Michael says" NThe new ersions of *isual ,tudio and A,6.NET add some interesting and o erdue features. 1ith A,6.NET J.K" Microsoft has mo ed the A,6.NET ABAM framewor% from a stand3alone e(tension to part of the .NET /ramewor%" and has rounded out its data 1e# controls offerings with the addition of the List*iew and Data6ager controls.N -eference5 http5SSaspnet.Xguysfromrolla.comSarticlesSEEHEIT3E.asp(!n !n this article we ha e had a loo% at some of the e(citing features added to A,6.NET and *isual ,tudio HIIL. 1e will learn more on each of these features in the forthcoming articles in this series. 1e will learn how we can ma%e use of such features in our we# application de elopment. )appy readingV

Das könnte Ihnen auch gefallen