for RuBoard |
Many of the new features in ADO.NET represent gently evolved ways to perform operations that ADO.old programmers have always done, but some features for accessing and presenting data are fairly abrupt departures from what you may be accustomed to. Here is a high-level summary of some of the most important data-access changes to an ASP.NET developer.
ADO.old provided support for sessionless access through the disconnected recordset. To disconnect from a data source in ADO.old, you had to remember to set a specific cursor type and perform a series of magic incantations to make the recordset disconnect from the server. And then, when it was all done, there wasn't any straight-forward way for the developer to determine whether the operation actually worked ”maybe it was disconnected, maybe not. Disconnected recordsets in ADO.old were both difficult to test and lacked adequately detailed documentation.
ADO.NET, on the other hand, makes it much easier to retrieve and manipulate disconnected data, including both relational constructs ( formed of rows and columns ) and hierarchical ones (such as XML documents). It does this through the use of a dedicated, always-disconnected object, the DataSet object, which we'll discuss at length later in this chapter.
Although it was possible to express data contained in the ADO.old Recordset object as XML, the process wasn't as straightforward as it might have been. Support for XML was added as an afterthought in ADO.old, and it was supported in an extremely clunky way; in fact, you could argue that ADO.old's XML support was so convoluted that it made sense to use it only in the context of data operability with other ADO data sources. This runs totally counter to the spirit of data interoperability using XML ”if the data can't go anywhere , there's really no point in using XML to begin with!
XML support in ADO.NET is provided through the DataSet object. The DataSet can always be rendered as XML with a single method call, and the XML that it renders is structured in a way that's easy to work with, whether you're working within the .NET framework or on some other platform.
Developers liked ADO.old because the number of objects it provided was small and easy to understand. In fact, it was possible to perform most common data operations with a limited knowledge of only two objects: the Recordset and Connection objects.
The architects of ADO.NET have attempted to divide its functionality in a more granular fashion. The objective behind this is to give you more lightweight objects. For example, if you don't need support for advanced features such as disconnected access and remoting via XML, you can use a DataReader object instead of the DataSet object. One unfortunate side effect is that there are more objects to learn. But the real advantage of a well-factored API is better performance and, in the long run, a simpler API. Now you don't have to internalize all the advanced features of ADO.NET until you're ready to use them.
A cursor is a software construct that enables your code to step though rows in a resultset one row at a time. There are different types of cursors; some cursors enable you to jump around from one record to another in the resultset with impunity (so-called scrolling cursors). In the Microsoft database cosmology, there are also "forward-only" or "firehose" cursors, which permit you only to move from the beginning of the recordset to the end without moving backward; some database programming purists argue that a cursor that does not scroll is not really a cursor at all.
In addition to scrolling or forward-only, cursors can reside in memory on the server or on the client. (For the purposes of this discussion, a middle- tier machine or a machine that provides access to data via Web services can be considered a client, too. Basically, any machine that is not the database server can be considered a client in this respect.) A server-side cursor allows you to perform server processing on the server without marshaling more results than you need to the client. Because marshaling data over the network can require a lot of time, database programmers sometimes turn to server cursors to perform processing for certain types of operations on database platforms (such as Microsoft SQL Server) that support them.
The problem with server-side cursors is that they consume resources on the server and provide only single-row access; server-side cursors don't support batch cursors.
In the meantime, one workaround is to embed server-side cursor functionality in a stored procedure, and then call that stored procedure using the normal ADO.NET techniques for calling stored procedures (described later in this chapter). The drawback of this workaround is that you must write your stored procedure in whatever language your database server uses. (This language is Transact-SQL if you're using Microsoft SQL Server.)
One of the most common questions developers ask when attacking a new API is how to do the most basic operations that they are accustomed to performing with the perfectly good API that they already use. Table 11.1 gives an example of some of the most common scenarios for database access and describes the approach you take to implement them in ADO.NET.
Scenario | Steps to Perform |
---|---|
Retrieve read-only data from a database | Open a connection; create a command object; create a DataReader object |
Retrieve data from a database in read/write mode | Open a connection; create a data adapter; assign commands for selecting, reading, writing, and updating to the data adapter; fill the DataSet |
Display the results of a query in a Web Forms control | Open a connection; create a data adapter; create a DataSet object; fill the DataSet; bind the control to a DataView object contained by the DataSet |
Manipulate query results as XML | Open a connection; create a data adapter; create a DataSet object; send XML from the DataSet to a XmlTextReader via a call to the DataSet's ReadXml method |
Retrieve a single (scalar) value from a query or stored procedure | Open a connection; create a command object; call the ExecuteScalar method of the command object |
Execute a stored procedure that inserts , updates, or deletes data | Open a connection; create a command object; call the ExecuteNonQuery method of the command object |
The remainder of this chapter describes how to perform these operations in detail.
for RuBoard |