ADO.NET introduction

Introduction to ADO.NET

As more and more companies are coming up with n-tier client/server and Web-based database solutions, Microsoft with its Universal Data Access (UDA) model, offers highperformance access to diverse data and information sources on multiple platforms. Also, UDA provides an easy-to-use programming interface that works with practically any cool or language, leveraging the technical skills developers already have.

The Microsoft UDA model is a collection of Data Access Components, which are the key technologies that enable Universal Data Access. The Data Access Components include ActiveX Data Objects (ADO), Remote Data Service (RDS), formerly known as Advanced Data Connector (ADC), Object Linking and Embedding Database (OLE DB), and Open Database Connectivity (ODBC).

Microsoft is targeting many more such Data Access components that offer easy-tomaintain
solutions to organizations. Such solutions are aimed at allowing organizations use their own choice of tools, applications, and data sources on the client, middle tier, or server. One of the emerging components within the UDAs collection is ADO.NET.

Microsoft ADO.NET is the latest improvement after ADO. ADO.NET provides platform interoperability and scalable data access. In the .NET Framework, data is transmitted in the Extensible Markup Language (XML) format. Therefore, any application that can read the XML format can process data. It is not necessary for the receiving component to be an ADO.NET component at all. The receiving component might be a Microsoft Visual Studio–based solution or any application running on any other platform.

Although ADO.NET preserves some of the primary concepts from previous ADO models, it has been chiefly stretched to provide access to structured data from diverse sources. ADO.NET provides access to diverse data sources by using a consistent and standardized programming model. ADO.NET is upgraded to offer several advantages over previous versions of ADO and over other data access components. ADO.NET builds the foundation of data-aware .NET applications. ADO.NET brings together all the classes that allow data handling. Such classes represent data container objects that feature typical database capabilities — indexing, sorting, and views. While ADO.NET offers a solution for .NET database applications, it presents an overall structure that is not as database-centric as the ADO model.

The ADO model uses the concept of recordsets, which are the ADO representation of tables and views from a database. Although these recordsets are very flexible to use and allow access to data even when disconnected from data sources, they suffer from a major drawback. In the case of distributed and Web applications, data needs to be exchanged among different components at different tiers, which might be running on variety of platforms. Of course, the format of the data being exchanged should be understood by all components. This transmission of data requires the conversion of data types of values to some data types that are recognized by the receiving components.

This conversion is called COM marshalling. Thus, the interoperability is limited when using ADO recordsets. So, the concept of ADO recordsets fails when we look at the Internet interoperability.
Like ADO, ADO.NET also allows you to access data when disconnected from actual data sources.

However, unlike ADO, ADO.NET uses XML as the data format. Because XML is a universal data format being used, ADO.NET expands the boundaries of interoperability to the Internet. In addition, instead of recordsets, ADO.NET uses the DataSet and DataReader objects to access and manipulate data. You'll learn about these objects later in the chapter. Thus, ADO.NET is designed to perform better and be more flexible than ADO. However, to support ADO objects, the corresponding equivalents exist in ADO.NET.


Data container objects are the objects that contain data to be transmitted to the receiving components. To take full advantage of ADO.NET, you should put some effort into understanding the concept itself, rather than simply figuring out the fastest way to port your code. Whatever
.NET programming model you might choose — Windows Forms, Web Forms, or Web Services — ADO.NET will be there to help you with data access issues.




Interoperability

The ADO.NET model is designed to take maximum advantage of the flexibility provided by the large industry acceptance of XML. ADO.NET uses XML for transmitting datasets among components and across tiers. Any component that is capable of reading the XML format can process the data. It is not necessary for the receiving component to be an ADO.NET component. The component that is sending or transmitting the dataset can simply transmit the dataset to its destination without bothering with how the receiving component is implemented. The component asking for the dataset, the destination component, can be implemented as a Visual Studio application or any other application.

However, the important point to be considered is that the receiving component should be capable of accepting the XML file formatted as a dataset.

Maintainability


After an application is deployed, there might be a need for changes in the application. For example, the application might need substantial architectural changes to improve its performance. As the performance load on a deployed application server grows, system resources can become inadequate, resulting in higher response times. As a solution to these problems, the application might need to undergo architectural changes by adding tiers. Here, the problem is not the multitier application design, but rather the problem lies in increasing the number of tiers after an application is deployed. This transformation becomes easier if the original application is implemented in ADO.NET using datasets.

In ADO.NET, the communication between tiers is relatively easy, because the tiers can
transmit data through XML-formatted datasets.

Programmability

The ADO.NET model uses typed programming to manipulate objects. In typed programming, the programming environment or programming language itself recognizes the types of things that are important to users. To take full advantage of typed programming, you must know the things that are of interest to programmers and to end users. Consider the following code using typed programming in ADO.NET:

If TotalQty > DataSet1.ProductInfo("Baby Food").QtyAvailable

his code is equivalent to a line using non-typed programming and is easier to read by end users. An end user who has little or no programming experience can easily grasp the meaning of the condition being tested. Also, in non-typed programming, if the developer makes a spelling mistake by chance (for example, ProductInfo is spelled as ProdcutInfo), a run-time error will get generated. On the other hand, in typed datasets,errors in the syntax caused by misspellings are detected at compile time rather than at run time.

Performance

In ADO, while transmitting data across tiers using COM marshalling in the form of disconnected RecordSets, the values must be converted to data types that are recognized by COM. This results in poor performance. On the other hand, ADO.NET is designed to use disconnected data architecture, which in turn is easier to scale because it reduces the load on database (does not require any data type conversions). Thus, in the ADO.NET model, everything is handled at the client side, which in turn improves performance.

Scalability

The Web-based, data-centric applications require multiple users to access data simultaneously. This increases the demand on data to be accessed, making scalability one of the most critical features. Applications that use resources, such as database connections and database locks, cannot support more users to access data simultaneously, because eventually the user demand for the limited resources will exceed their supply. Because ADO.NET uses disconnected data access, applications do not retain database locks or active database connections for long durations. Hence, ADO.NET accommodates scalability by encouraging programmers to conserve limited resources, and allows more users to access data simultaneously.

EVENTS IN DOT NET

Delegates and Events

Events are messages that indicate an interesting occurrence in another part of the application. When an event is raised, other parts of your application are given the opportunity to respond to that event by executing methods called event handlers.

Events are members of your class. An event represents a message that is sent to other parts of the application. When something noteworthy in the application occurs, your application can raise the event, which sends out the message. The event can wrap any arguments that contain information about the event and send them along with the event. Other parts of the application can handle the event, which means that a method is executed in response to the event.

Any method that handles an event must have the same signature as the event itself; that is, it must take the same kinds of arguments as the event passes. An event can be handled by more than one method, and a single method can handle more than one event.

Delegates

Central to the way in which events work are special classes called delegates. A delegate is essentially a type-safe function pointer. It allows you to pass a reference to the entry point for a method and invoke that method without making an explicit method call. When you declare a delegate, you specify the signature of the method that it can call and the return type.

In Visual C#, if you are creating a delegate to an instance method, you must initialize the delegate within a method. Delegates to static methods can be initialized outside a method.

Once declared and assigned, you can use the delegate to invoke the method in the same manner in which you would make a function call.

To create and invoke a delegate

Declare the delegate and provide a signature identical to the signature of the method(s) you want to invoke with this delegate.
Create an instance of the delegate that points to a method that has the appropriate signature.

Invoke the delegate by referencing its name.

Declaring and Raising Events

Declaring events is directly tied to delegates. In Visual C#, you must explicitly designate the delegate type that your event will use. Visual Basic .NET provides much of this functionality for you behind the scenes: you only need to supply the name of the event and the signature of the method it requires. A default delegate matching this signature is created.

To declare an event with Visual Basic .NET

Use the Event keyword to declare an event. Supply a signature that represents the signature of the type of method that you would like to handle the event. You can use any access modifiers, such as Public, Private, or Protected.

Implementing Event Handlers

Once an event is declared, it must be associated with one or more event handlers before it can be raised. An event handler is a method that is called through a delegate when an event is raised, and you must create associations between events and event handlers to achieve your desired results. If you attempt to raise an event in Visual Basic .NET that does not have any event handlers associated with it, nothing will happen. If you raise an event that has no event handlers in Visual C#, an error will result.

Like other members, there are instance events and Shared (static) events. Creating an event handler for an instance event requires that an association be made between a method and an object's event. The object must be declared in order for the event handler association to be created. Shared (static) events, however, belong to the class itself rather than any one instance of a class. To create an event handler for these events, you do not need to declare an instance of the class beforehand.


Event Handlers in Visual Basic .NET

In Visual Basic .NET, event handlers must be Subs and cannot return a value. You can associate a Sub with a given event by using the AddHandler keyword. AddHandler allows you to specify an event and designate a pointer to the method with which that event will be associated. The pointer is created using the AddressOf operator.

The AddHandler keyword cannot be used declaratively; it must be used inside a method. Thus, the association between the event and the event handler does not exist before the application's execution; it is added at run time. For event handler associations that exist for the lifetime of the object, the AddHandler keyword should be placed in the class's constructor.

Visual Basic .NET also allows you to create event handler associations at design time using the Handles clause. To use the Handles clause, the object must be declared with the WithEvents keyword. The WithEvents keyword informs the containing object that it will be receiving events from the contained object.

Event Handlers in Visual C#

Unlike in Visual Basic .NET, event handlers in Visual C# can return a value, and that value can be assigned to a variable in the same manner as a function call. You associate a method with a given method by creating a new instance of the appropriate delegate, which specifies the appropriate method and uses the += operator to make the association. You can also use the += operator to associate an event with an instance of a delegate that already exists.

Default delegates are provided for the events of the controls and classes of the .NET Framework base class library. If you want to manually add an event handler for one of these events, you do not need to declare a new delegate. Rather, you can create a new instance of the predefined default delegate. For example, the delegate class that is used for events for most of the controls in the System.Windows.Forms namespace is System.EventHandler.


To handle an event in Visual Basic .NET

Use the AddHandler keyword to create an association between an event and a method to handle that event. The AddressOf operator allows you to receive a pointer to the appropriate method. Event handlers must have the same signature as the event being handled.

Alternatively, you can use the Handles keyword to associate a method with an event at design time. The method must be a member method of an object that was declared with the WithEvents keyword.

To handle an event in Visual C#


Create an instance of the appropriate delegate for the event that specified the method that will handle the event, and use the += operator to associate the event with the delegate.


Event Handlers That Handle Multiple Events


You can create event handlers that handle multiple events. A common instance of when you might want to do this is when you have more than one instance of a class or control that raises the same events. For example, you might have a group of buttons on a form that share a similar role in the application. You might create a single method to handle the Click event for all of these buttons and distinguish between them by using the sender parameter.

Associating multiple events with a single handler is simple. You use the AddHandler or += operator in exactly the same way in which you would add a single event handler.

Events with Multiple Handlers

An event can be handled by more than one event handler. When an event is handled by more than one handler, all of the methods handling that event are executed. The order in which the methods execute is the same as the order in which the association was created. Thus, if event x is associated in code with handlers y, z, and q (in that order), when the event is raised, the order of handler execution will be y, z, and q. In Visual C#, if you are returning a value with your event, it will return the value of the last method executed.

To associate an event with multiple handlers, all you have to do is create an association between the event and each handler. In Visual Basic .NET, you can use the Handles clause to declaratively associate several methods with an event. If this method is used, the order of method execution is less predictable and should be tested if it has an effect on the dynamics of the application.

Removing Handlers at Run Time

You have already learned how to add event handlers dynamically. The AddHandler keyword in Visual Basic .NET and the += operator in Visual C# can be used to dynamically create associations between events and methods. You can also remove event handler associations at run time. For example, suppose you had a class that modeled a bank account that raised a NotSufficientFunds event every time the account's owner tried to submit a check for an amount greater than the account balance.

You might associate this event with two methods: a ChargeAccount method, which assesses a fee for writing a Not Sufficient Funds (NSF) check, and a Notify method, which notifies the owner of the account that his account is overdrawn. You would call the ChargeAccount method every time an NSF check was passed, but it would be redundant to call the Notify method more than once until the account balance became positive. In this case, you could remove the event handler for the Notify method, and reinsert it when the account balance returned to the positive side.

The method by which you remove an event handler is very similar to the method by which you add one. In Visual Basic. NET, you use the RemoveHandler method to disassociate an event from a delegate obtained with the AddressOf operator. In Visual C#, you use the -= operator to dynamically remove an association between an event and a method. This operator requires a reference to a delegate of the appropriate signature, and it must reference the method to be removed.