1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional ASP.NET 1.0 Special Edition- P17 docx

40 158 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Using a Stored Procedure with a Command Object
Trường học Wrox
Chuyên ngành Web Development
Thể loại Sách chuyên khảo
Năm xuất bản N/A
Thành phố N/A
Định dạng
Số trang 40
Dung lượng 921,36 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The example Updating Data with a Stored Procedure update-with-storedproc.aspx shows how we can use a Command object to execute a stored procedure that updates the source data.. We also

Trang 1

have carried out the operation in previous versions of ADO And we can use INSERT and DELETE statements in exactly the same way as we used an UPDATE statement in this example

However, it's often preferable to use a stored procedure defined within the data store to perform data updates Stored procedures can provide a useful increase in performance, hide the structure of a database table from inquisitive users, and allow finer control over security permissions The next example demonstrates how we can use a similar technique to that above with a stored procedure instead of a SQL statement

Using a Stored Procedure with a Command Object

Using a stored procedure with a Command object is a fundamentally similar process to using a SQL statement, as we discovered in the previous chapter when we were extracting data from a data store The example Updating Data with a

Stored Procedure ( update-with-storedproc.aspx) shows how we can use a Command object to execute a stored procedure that updates the source data

The stored procedure named AddNewBook is created within the WroxBooks database by the SQL script we provide in the samples It inserts a new row into the BookList table using values provided in parameters to the stored procedure, and returns zero (0) if it succeeds in inserting the new row:

However, to make the process repeatable when you are experimenting with the samples, we've added a rather unusual twist to the procedure (one which is unlikely to be found in a real-world application) If we hadn't done this, you would only

be able to run the procedure once unless you manually deleted the row in the database, or edited the procedure to insert

a different row

What the procedure does is to first check to see if a book with the specified ISBN (the primary key of the table) already exists If it does exist, it deletes this row from the table instead - and returns minus one (-1) as the result This way, you can run the page as many times as you wish:

Trang 2

The AddNewBook Stored Procedure

The stored procedure takes as input parameters the ISBN code, title, and publication date of the book to be inserted, and

it has a fourth Integer-type output parameter to hold the result This is what it looks like:

CREATE PROCEDURE AddNewBook

@ISBN varchar(12), @Title varchar(100), @Date datetime,

@Result integer output AS

SELECT ISBN FROM BookList WHERE ISBN=@ISBN

IF @@ROWCOUNT = 0

BEGIN

INSERT INTO BookList(ISBN, Title, PublicationDate)

VALUES (@ISBN, @Title, @Date)

SELECT @Result = 0

Trang 3

The Code for the Stored Procedure Update Example

In this example we're executing a stored procedure, so our command text is just the name of the stored procedure - AddNewBook We start by specifying this and displaying it in the page:

'specify the stored procedure name

Dim strSQL As String = "AddNewBook"

outSQL.InnerText = strSQL 'and display it

Now we create our connection and command objects as before However, for maximum execution efficiency, we need to specify this time that the command text is the name of a stored procedure:

Dim objConnect As New OleDbConnection(strConnect)

Dim objCommand As New OleDbCommand(strSQL, objConnect)

objCommand.CommandType = CommandType.StoredProcedure

Creating the Parameters

Next we create the parameters we'll need within the Parameters collection of the Command object The first is for the

Trang 4

ISBN code and is of type OleDbType.VarChar and length 12 characters We also specify that it's an input parameter, and set the value:

'create a variable to hold a Parameter object

Dim objParam As OleDbParameter

'create a new Parameter object named 'ISBN' with the correct data

'type to match a SQL database 'varchar' field of 12 characters

objParam = objCommand.Parameters.Add("ISBN", OleDbType.VarChar, 12)

'specify that it's an Input parameter and set the value

objParam.Direction = ParameterDirection.Input

objParam.Value = "1999999999"

The process is repeated for the next two input parameters, the book title and publication date Note that the publication date parameter (named Date) is of type OleDbType.DBDate, and we have to specify the value in a format that corresponds to the column in the database In the case of a SQL datetime column, the format "yyyy-mm-dd" will work:

'create a new Parameter object named 'Title' with the correct data

'type to match a SQL database 'varchar' field of 50 characters

'specify that it's an Input parameter and set the value

objParam = objCommand.Parameters.Add("Title", OleDbType.VarChar, 50)

objParam.Direction = ParameterDirection.Input

objParam.Value = "Programming in the Virtual World"

'create another input Parameter object named 'Date' with the correct

Trang 5

'data type to match a SQL database 'datetime' field

'specify that it's an Input parameter and set the value

objParam = objCommand.Parameters.Add("Date", OleDbType DBDate)

objParam.Direction = ParameterDirection.Input

objParam.Value = "2001-05-01"

The final parameter is named Result, and is an output parameter that will return the result of executing the stored procedure It returns an integer value, and so we specify OleDbType.Integer in this case:

'create an output Parameter object named 'Result' with the correct

'data type to match a SQL database 'integer' field

'specify that it's an Output parameter so no value required

objParam = objCommand.Parameters.Add("Result", OleDbType.Integer)

objParam.Direction = ParameterDirection.Output

Before executing the stored procedure, we display the input parameter values in the page - within a <div> element named outInParams We can read their current values directly from the Parameters collection by specifying the name

of each one:

'display the value of the input parameters

outInParams.InnerText = "ISBN='" & objCommand.Parameters("ISBN").Value _

& "' Title='" & objCommand.Parameters("Title").Value _

& "' Date='" & objCommand.Parameters("Date").Value & "'"

Trang 6

Executing the Stored Procedure

The next step is to execute the stored procedure In this case, we don't have any returned value for the number of rows affected, so we don't need to capture the result of the ExecuteNonQuery method:

Try

objConnect.Open()

objCommand.ExecuteNonQuery()

objConnect.Close()

Catch objError As Exception

outError.InnerHtml = "* Error while updating original data.<br />" _

& objError.Message & "<br />" & objError.Source

Exit Sub

End Try

Once the stored procedure has been executed, the parameter named Result will contain the result of the process We collect its value from the Parameters collection of the Command object In our example, we also display the value - plus

an accompanying explanation message - in a <div> element named outOutParams within the page:

'collect and display the value of the output parameter

Dim intResult As Integer = objCommand.Parameters("Result").Value

Dim strResult As String = "Result='" & CStr(intResult) & "'<br />"

If intResult = 0 Then

Trang 7

strResult += "Successfully inserted new book details"

Else

strResult += "Failed to insert new book details and instead " _

& "deleted existing record with this ISBN"

End If

outOutParams.InnerHtml = strResult

Updating Data Sources with Transactions

One of the features of most database systems, and some other types of data store, is the ability to use transactions Simply put, a transaction is a series of events that are all completed, or of which none are completed - there is never an intermediate result where some but not all of the events within the transaction occur

The name 'transaction' comes from real-world scenarios such as purchasing an item in a store where you give the seller money in exchange for goods Unless one of you gets cheated, the transaction will either succeed with both parties happy

at the outcome (you pay your money and get your goods), or fail where neither action occurs There should never be an outcome where you pay money and don't get the goods, or where you get goods but don't pay the money

In this section, we'll look at two types of transactions:

ƒ Database transactions, where database-specific statements control the transaction, and it is carried out within the database itself Usually the stored procedure within the database contains the transaction statements

ƒ Connection-based transactions, where the statements that control the transaction, and the execution and management of that transaction, are outside the database Usually these are a feature of the Connectionobject that executes a SQL statement or stored procedure

While it is possible to write stored procedures that perform transactions across different databases on the same server, this is outside the scope of this chapter It is also possible to use the services of another application, such as Windows

2000 Component Services (or MTS in Windows NT4) to perform a distributed transaction, where a series of events spread across different databases and applications on different servers are managed as a single transaction Chapter 17 (".NET Components") briefly looks at this topic

Trang 8

Database Transactions

In a database system such as SQL Server, we specify transaction operations within a stored procedure using

vendor-specific statements like BEGIN TRANSACTION to start a new transaction, COMMIT TRANSACTION to accept all the updates and permanently commit the changes to the data, and ROLLBACK TRANSACTION to cancel all the changes made within the current transaction

We've provided an example page that uses a transacted stored procedure The stored procedure, named

DoBookArchive, is created within the WroxBooks database by the SQL script we provide with the samples

The DoBookArchive Stored Procedure

The DoBookArchive stored procedure moves a row from the BookList table into another table named ArchiveBooks, within the same database If the process succeeds, the transaction is committed and the updates are permanently applied

to the database tables If there is an error when writing to the ArchiveBooks table, or when deleting the book from the BookList table, both actions are rolled back and the tables are left in exactly the same state as before - neither is affected by the procedure

However, to make it repeatable while you are experimenting with the example, the stored procedure always starts by deleting any existing book with the same ISBN (the primary key) in the ArchiveBooks table This action will also be rolled back if the complete transaction fails, so if a book has been archived (and hence deleted from the BookList table)

it will not be deleted from the ArchiveBooks table if you run the stored procedure again with the same ISBN In this case, the INSERT statement will fail because the book is not in the BookList table, and so the entire transaction is rolled back undoing the DELETE operation on the ArchiveBooks table

This is the code for the stored procedure:

CREATE PROCEDURE DoBookArchive

@ISBN varchar(12), @Result integer output AS

DECLARE @verror int

BEGIN TRANSACTION

DELETE FROM ArchiveBooks WHERE ISBN=@ISBN

INSERT INTO ArchiveBooks (ISBN, Title, PublicationDate)

Trang 9

SELECT * FROM BookList WHERE ISBN LIKE @ISBN

SELECT @verror = @@ERROR, @Result = @@ROWCOUNT

IF @verror <> 0 GOTO on_error

IF @Result > 0

BEGIN

DELETE FROM BookList WHERE ISBN=@ISBN

IF @@ERROR <> 0 GOTO on_error

The Transacted Stored Procedure Example

The example page Updating Data with a Transacted Stored Procedure (transacted-storedproc.aspx) uses the stored procedure we've just described We've arranged for it to use the same ISBN code as the previous example that

Trang 10

inserts and deletes a book in the BookList table, so that you can see the results of this example by running it after inserting the new book and after deleting it Providing that you have run the previous example to insert the new book row, the stored procedure in this example will succeed:

If you then run the page again, it will show that the stored procedure failed to find the book in the BookList table (because, of course, it's just been moved to the ArchiveBooks table):

The Code for the Transacted Stored Procedure Example

As in our earlier examples, we start by specifying the name of the stored procedure and displaying it in the page, and then create the Connection and Command objects we'll need to execute it We also set the CommandType of the Command

Trang 11

object to indicate that we'll be executing a stored procedure:

'specify the stored procedure name

Dim strSQL As String = "DoBookArchive"

outSQL.InnerText = strSQL 'and display it

Dim objConnect As New OleDbConnection(strConnect)

Dim objCommand As New OleDbCommand(strSQL, objConnect)

objCommand.CommandType = CommandType.StoredProcedure

Now we create the parameters for the command This time there are only two - an input parameter to hold the ISBN of the book we want to archive, and an output parameter to hold the result:

Dim objParam As OleDbParameter

'create an input Parameter object named 'ISBN' with the correct data

'type to match a SQL database 'varchar' field of 12 characters

objParam = objCommand.Parameters.Add("ISBN", OleDbType.VarChar, 12)

objParam.Direction = ParameterDirection.Input

objParam.Value = "199999999"

'create an output Parameter object named 'Result' with the correct

'data type to match a SQL database 'integer' field

'specify that it's an Output parameter so no value required

Trang 12

objParam = objCommand.Parameters.Add("Result", OleDbType.Integer)

objParam.Direction = ParameterDirection.Output

'display the value of the input parameter

outInParams.InnerText = "ISBN='" & objCommand.Parameters("ISBN").Value & "'"

The next step is to open our connection and execute the stored procedure:

Try

objConnect.Open()

objCommand.ExecuteNonQuery()

objConnect.Close()

Catch objError As Exception

outError.InnerHtml = "* Error while updating original data.<br />" _

& objError.Message & "<br />" & objError.Source

Exit Sub 'stop execution

End Try

Then we can collect the result from the output parameter and display it, along with some accompanying explanatory text:

'collect and display the value of the output parameter

Dim intResult As Integer = objCommand.Parameters("Result").Value

Dim strResult As String = "Result='" & CStr(intResult) & "'<br />"

Trang 13

Select Case intResult

Case -1: strResult += "Error occurred while attempting archive"

Case 0: strResult += "Failed to archive book -no matching book found"

Case > 0: strResult += "Successfully archived the specified book"

End Select

outOutParams.InnerHtml = strResult

Notice that we didn't have to do anything extra to benefit from the transaction within the stored procedure - we just executed it and checked the result to see what actually happened This is not the case, however, when we use the other type of transaction, a connection-based transaction We'll see how different working with this type of transaction is next

Connection-based Transactions

The previous example demonstrates how we can use a transaction within a stored procedure (a database transaction) to ensure that a series of operations on our data either all succeed or are all rolled back A second way of using a transaction

is through the capabilities of the Connection object

Both the SqlConnection and the OleDbConnection objects can be used to perform transacted data updates While the way we actually apply a transaction is different from the stored-procedure transaction we used in the previous example, the terminology is broadly the same:

Connection.BeginTransaction Starts a new transaction on this connection and all subsequent changes to the data

become part of the transaction until it is committed or rolled back

Transaction.Commit Commits all changes made to the data within this transaction since it was started

The changes are made permanent in the target data store

Transaction.Rollback Abandons all changes made to the data within this transaction since it was started

The changes are removed from the target data store

The Transaction Object

In ADO.NET, we have two objects that implement transactions - SqlTransaction for use with Microsoft SQL Server via TDS, and OleDbTransaction for use with an OLE-DB provider (there is also an equivalent OdbcTransaction object currently under development) To start a transaction we call the BeginTransaction method of the current

Connection object This returns a Transaction object that we must then assign to any Command objects that we want

Trang 14

to enroll into that transaction

To end a transaction and commit all the changes to the database, we call the Commit method of the Transaction object (note that it's not a method of the Connection object as you might at first have expected) To abandon all changes to the data, we call the Transaction object's Rollback method instead

Notice also that we have to manually enroll any Command objects into the transaction While this might seem odd, it does allow us to have multiple transactions in progress, and use whichever is appropriate for each command we carry out on the database We can also create a nested transaction (that is a transaction that executes within another transaction) by creating a new Transaction object and calling the Begin method

A Connection-based Transaction Example

To see the transaction methods in action, open the example Transactional Data Updates with a Command Object (update-with-transaction.aspx) This page creates three SQL statements that are used to update the titles of three books in the BookList table to reflect the current date and time, and then it executes these statements Afterwards, it reads the rows back from the database and displays the details to confirm that the updates were successful:

You can see in the previous screenshot that the transaction was committed, and the three rows were updated However, this is only because the page contains logic that uses the current time in seconds to decide whether to commit or roll back the transaction While not a real-world scenario, it is done so that you can see the result of rolling back a transaction as well as committing it After running the page again where the time has an even number of seconds, the transaction is rolled back and so the titles are not updated:

Trang 15

The Code for the Connection-based Transaction Example

The only real differences in the way that this page works, when compared to the other examples that use SQL statements

to update the data source, is that we have to call the transaction methods at the appropriate times - effectively managing the transaction ourselves Instead of a stored procedure within the database itself deciding whether to commit or rollback the changes (usually dependent on the outcome of one of the statements in the stored procedure), we decide within our ASP code if the transaction should be committed or rolled back

As usual, we start by creating the SQL statements we'll be executing against the BookList table to update the book titles:

'specify the SQL statements to update the data

Dim strNow, strSQL1, strSQL2, strSQL3 As String

Dim datNow As DateTime = Now()

strNow = datNow.ToString("dd-M-yy \a\t hh:mm:ss")

strSQL1 = "UPDATE BookList SET Title = 'Book One Written on " _

Trang 16

& strNow & "' WHERE ISBN='1861009901'"

outSQL1.InnerText = strSQL1 'and display it

strSQL2 = "UPDATE BookList SET Title = 'Book Two Written on " _

& strNow & "' WHERE ISBN='1861009902'"

outSQL2.InnerText = strSQL2 'and display it

strSQL3 = "UPDATE BookList SET Title = 'Book Three Written on " _

& strNow & "' WHERE ISBN='1861009903'"

outSQL3.InnerText = strSQL3 'and display it

Then we create our Connection and Command objects, and declare a variable to hold the number of rows affected by our updates We've set the initial value to zero here, though this is not actually required (zero is the default value), but it helps

to illustrate how the code works, and ensures that we can safely add on the result each time we execute a SQL statement:

Dim objConnect As New OleDbConnection(strConnect)

Dim objCommand As New OleDbCommand()

Dim intRowsAffected As Integer = 0

Starting a Transaction

We need a variable to hold the Transaction object that will be returned when we start a transaction, and so we declare this next:

'declare a variable to hold a Transaction object

Dim objTransaction As OleDbTransaction

Trang 17

Next we open our connection, and execute the BeginTransaction method to start a new connection-based transaction

We assign the Transaction object that is returned to our objTransaction variable:

'specify the Connection object and command type for the Command

objCommand.Connection = objConnect

objCommand.CommandType = CommandType.Text

'attach the current transaction to the Command object

'must be done after setting Connection property

objCommand.Transaction = objTransaction

Notice that we can only do so after we've set the Connection property, and if we want to change the Connection

property afterwards we first have to un-enrol it by setting the Transaction property of the Command to Nothing

Then we can assign each SQL statement to the CommandText property in turn and execute it:

'specify the select statement to use for the first update

Trang 18

objCommand.CommandText = strSQL1

'execute the SQL statement against the command to fill the DataReader

'keep track of number of records originally updated

Transaction object to cancel any changes that have been applied to the source data:

Catch objError As Exception

'error encountered so roll back all the updates

objTransaction.Rollback()

'display error details

outError.InnerHtml = "* Error while updating original data.<br />" _

& objError.Message & "<br />" & objError.Source

Trang 19

Exit Sub ' and stop execution

End Try

After successfully executing all three statements without an error, we would normally call the Commit method of the Transaction object to permanently apply the changes to the data store However, in our example, we check the number of seconds in the current time and only call Commit if this is an odd number If it's an even number, we call the Rollback method to abandon all updates:

'all seems OK so can now commit all the updates However as an

'illustration of the technique only do so if the current time

'has an odd number of seconds If not, rollback all changes

Dim strCommit As String

Afterwards we can read the values of the rows using a DataReader object and display them in the page This is identical

to the way we did it in the first example in this chapter, so we aren't repeating the code here

Having looked briefly at how we can use transactions to ensure multiple data updates all succeed, or all fail, we'll move

on to a different topic The DataSet object we introduced in previous chapters has the facility to automatically update the source data from which it was created - or in fact any data store for which the structure and contents of the tables within

Trang 20

the DataSet are of the appropriate format This is the focus of the next section

Updating Data from a DataSet Object

In previous chapters we've regularly used a DataSet object to store data extracted from a database, or to hold data that we've created dynamically using code We also looked at the ways we can edit and modify the data that the DataSetcontains In this section of the chapter, we'll look in detail at how we get those changes back into a data source such as

a relational database

ADO.NET includes the DataAdapter object, which is used to provide the connection between a data store and a disconnected DataSet We saw this object in action in Chapter 8, but only so far as collecting rows from a database and pushing them into a DataSet To understand how the update process works for a DataSet, we need to examine the DataAdapter object in more depth

Inside the DataAdapter Object

In order to understand and take advantage of many of the features of the NET disconnected data model, especially when

we come to look at concurrent data update issues later in this chapter, you must be comfortable with what's going on behind the scenes when you use the DataSet and DataAdapter objects to push changes made to the data back into a data source

The full chain of objects that are required to pull data from a data store into a DataSet, and push the changes back into the data store after updating, is shown in the next schematic You can see the four main objects that are involved in the process - the Connection, Command, DataAdapter, and DataSet:

Ngày đăng: 03/07/2014, 07:20

TỪ KHÓA LIÊN QUAN