+ All Categories
Home > Technology > Introduction to ado.net web forms

Introduction to ado.net web forms

Date post: 28-Jun-2015
Category:
Upload: apex-tgi
View: 154 times
Download: 6 times
Share this document with a friend
Description:
ASP.NET Web Forms is a part of the ASP.NET web application framework and is included with Visual Studio. It is one of the four programming models you can use to create ASP.NET web applications, the others are ASP.NET MVC, ASP.NET Web Pages, and ASP.NET Single Page Applications.
Popular Tags:
40
1 .NET Web Forms ADO .NET Introduction K
Transcript
Page 1: Introduction to ado.net web forms

1

.NET Web Forms

ADO .NET Introduction

K

Page 2: Introduction to ado.net web forms

2

ADO .NET Overview

ASP .NET CodeDatabase

Web Form

Data Controls

Data Connector(Establishes connection and opens the database.)

Data Adapter(Translates commands and exchanges data.)

SQL

Data and

Errors

Data Set (Collection of tables and relationships.)

*CustomerIDLastNameFirstName

Data Table Data View (Based on 1 table.)

ORDER BY LastNameWHERE …

Data Relationship (Associations among tables.)

Fill

Data Bind

Major question: What is missing? Hint: it is missing in ADO .NET, not just the diagram.Answer: save data

Page 3: Introduction to ado.net web forms

3

Sample Project: Simple2

You should create a new sample project to test your skills. The completed version should look something like: Simple2

Page 4: Introduction to ado.net web forms

4

Data Connector The Data Connector is usually straightforward. The wizard starts automatically when you add a Data Adapter. Choose the type of database (that picks the provider and the specific

connector). Enter the connection information—usually location.

Access: Specific physical path.Oracle: Oracle connection information

Registered nameUser nameUser password

SQL Server connection information (but use the SQL Adapter)ServerUser nameUser password

SQL Server has many shortcuts and tricks within Visual Studio

The connector simply establishes the communication links to the database.

Page 5: Introduction to ado.net web forms

5

Data Connector Challenges ADO .NET difficulties

Access problem is that it is hard to change the location later. It is also difficult to change databases later (SQL Server to Oracle).

Partial Solution (but critical) Store all DB specific code in one place. Do not scatter database code across your application and forms. Before building any database forms, create a new blank Component

for the sole purpose of holding all primary database definitions. Solution Explorer + Add + Add New Item + Component Class: DBMain

To create a database connection, simply drag one onto the design screen of the new component, and fill in the wizard properties. Select a provider

Access: Jet 4.0 Oracle: Oracle Provider for OLE DB (maybe Microsoft version) SQL Server: Use the SQL Adapter instead!

Rename the connector: cnnOle

Page 6: Introduction to ado.net web forms

6

TMF: Things Microsoft Forgot

I developed some standard routines to handle several common issues. They are stored in a class called TMF. You will eventually end up adding this class to most of your forms. First, add the file to your project, right-click + Add + Add Existing:

TMF.vb (you only have to do this once). Second, for any form that you need the routines, open the Code View

(View + Code, or right-click); add one line of code, often at the top, along with the control definitions:

Dim tmf As TMF = New TMF()

Details of the routines will be explained in future slides as they are needed.

Notes and some documentation are written as comments in the file.

Page 7: Introduction to ado.net web forms

7

Data Connector: Access Flexibility

One problem with the Access connector is that it relies on a fixed pathname, making it difficult to move the database. You need to add the special TMF (Things Microsoft Forgot) component to

your project (Add + Existing File). In the DBMain component, expand the Component Designer Generated

region, in the Public Sub New(), after InitializeComponent, addDim tmf As New TMF()Dim strCS As StringstrCS = tmf.GetCnnString("cnnOleCareer")If (strCS <> "") Then Me.cnnOleCareer.ConnectionString = strCS

In the Web.config file, right before the end </configuration>, add/modify<appSettings>

<!-- User application and configured property settings go here.--><!-- Example: <add key="settingName" value="settingValue"/> --><add key="cnnOleCareer.ConnectionString" value="" /><add key="cnnOleCareer.DataSource" value="../Database/career.mdb" />

</appSettings> This approach uses a relative path, so you can move the entire project.

Page 8: Introduction to ado.net web forms

8

Data Adapter Comments

Data Adapter Is responsible for translating SQL requests to the chosen type of

database and returning data rows and messages. Every command or table that you want to access must be associated

with a data adapter. Technically, a data adapter can handle several different tables. But, unless the tables will be related (parent/child), it seems easier to

create a separate data adapter for each table. Biggest drawback is that SQL Server uses a different data adapter

than Access/Oracle. So, if you want to change DBMSs later, you have to replace all of the adapters!

Critical: Keep all data adapters in one (maybe two) locations: the DBMain component.

Creating a data adapter From the Data toolbox, drag an adapter onto the main DB component.

(Ole for Access or Oracle, Sql for SQL Server). Answer the wizard questions. To change later: Configure Data Adapter

Page 9: Introduction to ado.net web forms

9

Create Data Adapter: Query Type

First, choose your database connection (not shown here).

Second, choose the type of query to use. Access only supports text

SQL. SQL Server and Oracle will

generally run faster if you use a stored procedure, which is a parameterized view stored and precompiled on the database server.

If you let the wizard build the procedure, you should go back to the database and double-check it.

Page 10: Introduction to ado.net web forms

10

Create Data Adapter: Query Type

Create the SQL statement to retrieve the data from tables or existing views.

Use the Query Builder to minimize typing errors.

Warning: if you pull data from more than one table (or from a view that uses more than one table), .NET will not be able to edit that data.

Query Builder (next slide) Advanced Options (slide)

Page 11: Introduction to ado.net web forms

11

Data Adapter: Query Builder

Add tables Click columns to add: Warning,

they are displayed in the order in which you add them. You can move them later, but it is easier to do it right now.

Note that columns that are reserved words should use brackets. When in doubt, use brackets.

If you use more than one table, .NET will not be able to edit the data.

If you JOIN tables, do it in the database itself and use a simple query here to pull from that view. Portability!

Page 12: Introduction to ado.net web forms

12

Data Adapter: Advanced Options If you only need to retrieve data (not

change it), uncheck all of these options.

In some situations, you will want to skip the optimistic concurrency. If you uncheck this box, all changes will be written to the database, even if someone else changed the data immediately before you.

The third option is only available with SQL Server and Oracle (databases that support query languages that can do more than one thing). Useful if you insist on using Identity (AutoNumber) columns and need to insert rows.

Page 13: Introduction to ado.net web forms

13

Data Set Overview

A Data Set is roughly a miniature in-memory copy of part of your database. You specify which tables you want to include. You can build relationships (usually parent/child). You can create Data Views, but data views are not queries. They

cannot perform JOINs. They can only sort and filter a single data table.

Technically, a data set can contain multiple tables, but that feature only seems to be useful if you have related tables. Even then, it is not as useful as you might think.

Major issue: the data set is an in-memory copy of your database. The server has to hold the data in memory. Once you send your page to the user, the data set is discarded by the

server. If you want to keep it for postback/roundtrips, you have to store the dataset some place. Session variable?

Bottom line: big data sets are a disaster!

Page 14: Introduction to ado.net web forms

14

Data Set: Generate

Once the adapter is created, it is easy to generate a data set in the main DB component. Right-click on the adapter. Generate Data set Select New and enter a unique

data set name. Make sure the proper table is

checked. Check the box to add it to the

designer.

If you need to delete a dataset, you will have to delete it from the .xsd list of files (and delete it from the DB code).

Page 15: Introduction to ado.net web forms

15

What We Have So Far

A Data Connection that can open the database A Data Adapter that can send SQL to the database and receive

data rows. A definition of a Data Set that can temporarily hold data that is

read from one table (or view). You can add other adapters and datasets. You can create relationships if there are parent/child tables, but you

will see that these are not very useful.

Things we do not have yet. There is no data in the data set. The data set is not connected to the form

Page 16: Introduction to ado.net web forms

16

Filling the Data Set

In the main DB component (View + Code) add a subroutine:

Public Sub FillEmployee(ByVal ds As DataSet)

adpEmployee.Fill(ds)

End Sub

At first glance, the routine seems pointless, but its purpose is to keep the database-specific code in one component. Remember that the adapter is specific to the database. This way, your form can use the dataset only, while the adapter stays in the one component.

We will add code to your data form to call this routine.

Page 17: Introduction to ado.net web forms

17

Creating the Data Form

Three basic types of forms are commonly used in business applications. Each has slightly different considerations and setup. They will be covered in later lessons.

Consider a standard form with one row of data. To start, add a new blank Web Form, named Employee Drop a Data Set onto the blank design. Select the employee data

set you created earlier. Then do View + Code to see the code. You need to tell the form to go to the database and fill the data set

with data. There are two possible times/places to do this: Page_Load or Page_Init. For now, Page_Load is easier. Near the top of the class, add:

Protected cmpMain as New DBMain()

Protected tmf As New TMF() In the Sub Page_Load, add:

cmpMain.FillEmployee(DsEmployee1)

Page 18: Introduction to ado.net web forms

18

Starting the Data Form Page

Add a style. Open the style sheet and add a class for PageTitle Choose a font family (e.g., Arial) and font size (e.g., 2 em) In Text, set the horizontal alignment to Centered Save and close the style sheet and drop it onto the data form.

Add a Title. From the Web Forms toolbox, Drop a Label near the top of the form In the Text property, enter the title: Employee Set the CssClass: PageTitle Change the ID: lblPageTitle (not strictly required, but a useful habit)

Link the page. Open the main form (rename it, e.g., AAStart) Add the style sheet and a title. Add a HyperLink that opens the data form. Set: Text (Employee Form), ID (lnkEmployee), NavigateURL

(Employee.aspx) Save everything and build and browse to test it. If the DB form

crashes, check the security settings first.

Page 19: Introduction to ado.net web forms

19

Adding Data Controls

Design view on the data form. Drag and drop labels and text boxes onto the form. Keep a list handy for the data columns. For labels, set properties

ID: lblColumn lblEmployeeID Text:Column Employee ID

For text boxes, set properties ID: txtColumn txtEmployeeID Tab Index Number from top to bottom (0 … 5)

Add a Button, Call it Save (ID=btnSave) (Do not write code for it yet). Use Format Menu to vertically space and align everything.

Data binding the controls For each text box, click the Data Binding property Choose simple binding, and click your way down the list until you can

select the matching column. (See next slide)

Page 20: Introduction to ado.net web forms

20

Simple Data Binding

Make sure Text property is selected on the left.

Click your way down the list on the right until you can select the matching data column.

You can set a format, for example for dates.

Page 21: Introduction to ado.net web forms

21

Activate Data Binding The control properties simply set a mapping from the dataset

table to the control. You still need to activate the binding and transfer the data.

Each control has a DataBind method that performs this one-way transfer.

But, it is easier to use the Page.DataBind method because it does the transfer for all of the controls.

The problem: Calling DataBind replaces the content of target, destroying whatever

was there before. Forms use a PostBack approach. When users click a button, the data

is sent back to the same page. You must avoid destroying the data changed by the user.

In Page_Load, add: Test it

If Not Page.IsPostBack ThenPage.DataBind()

End If

Page 22: Introduction to ado.net web forms

22

Saving Data: The Simple Approach When you created the data adapter, by default, it created SQL

statements to Update, Insert, and Delete. If the data in the in-memory data set changes, ADO .Net can

automatically apply the changes (including insert and delete) back to the stored database.

First, in the Main database component, add:Public Sub UpdateEmployee(ByVal ds As DataSet)

adpEmployee.Update(ds)End Sub

In the data form, write code for the Save button to transfer the form data to the data set. Double-click the Save button to start. Add:

DsEmployee1.Tables("Employee").Rows(0).BeginEdit()DsEmployee1.Tables("Employee").Rows(0)("EmployeeID") = txtEmployeeID.TextDsEmployee1.Tables("Employee").Rows(0)("LastName") = txtLastName.Text

… (do all of the columns)DsEmployee1.Tables("Employee").Rows(0).EndEdit()cmpMain.UpdateEmployee(DsEmployee1)

Page 23: Introduction to ado.net web forms

23

Problems with the Simple Approach

We have ignored concurrency issues. It would actually be better if you build the dataset without testing for

concurrency. Right now, if someone else changes the data, the update will crash, and

cannot be recovered unless you back out of the form and reload the data from the database.

However, notice that every time the form is loaded, including during post back, the page goes to the database and gets the current version. So, this version will actually overwrite most changes made by other people with no warning. The only concurrency issue that will be caught and crashed is on the server between re-reading the page and writing the new data; which is a relatively minor chance.

It will be incredibly boring to duplicate these steps for every form you will have. It will also be painful to return later and make changes.

Note that the dataset is not saved across post back. Which is probably good, since the system is designed to read the entire table. Which is crazy, since the form only uses one row at a time.

Page 24: Introduction to ado.net web forms

24

Customer Form: A Better Method It is pointless and painful to have to write the same complex update

code every time you need a form. So, I created some generic routines to help. This example relies heavily on them. Make sure you have the TMF file in your project. Copy the generic code from the DBMain in the sample project. (especially

BatchUpdate and MergeConcurrency)

Getting started Create the Data Adapter in DBMain as usual, be sure to take the default to

generate optimistic concurrency. Generate the Data Set as usual. Keep a copy of the column names. Add two routines to the DBMain code:

Public Sub FillCustomer(ByVal ds As DataSet, ByVal sID As String) Dim tmf As TMF = New TMF() adpCustomer.SelectCommand.CommandText = tmf.AddWhereToSelect(adpCustomer.SelectCommand.CommandText, "CustomerID=" & sID) adpCustomer.Fill(ds)End SubPublic Function UpdateCustomer(ByVal ds As DataSet, ByVal sID As String) As String

Return BatchUpdate(ds, adpCustomer, "Customer", AddressOf Me.FillCustomer, sID)End Function

Page 25: Introduction to ado.net web forms

25

Customer Form: Construction

Create a new Web Form for Customer. Add the style sheet and Page Title Add the data set Add the labels and text boxes, set the tab index Use DataBinding to link the text boxes to the dataset. Add the Save button (do not write code yet) Add a blank Label at the top, across the page, ID: lblMessage

View + Code, below the control definitions (Protected WithEvents )

Protected cmpMain As DBMain = New DBMain()Protected tmf As tmf = New tmf()

Page 26: Introduction to ado.net web forms

26

Customer Form: aryColumns

The generic code needs a method to map the column names to the controls. The easiest method is to create a special array above the Page_Load routine. For each column, you enter Column Name Control ID Type of control (Text, Label, DDL, Check) Whether or not the column is part of the primary key

Private aryColumns() As tmf.SingleEditItem = { _New tmf.SingleEditItem("CustomerID", "txtCustomerID", "Text", True), _New tmf.SingleEditItem("FirstName", "txtFirstName", "Text", False), _New tmf.SingleEditItem("LastName", "txtLastName", "Text", False), _New tmf.SingleEditItem("Address", "txtAddress", "Text", False), _… Do all of the columns …New tmf.SingleEditItem("EMail", "txtEmail", "Text", False), _New tmf.SingleEditItem("URL", "txtURL", "Text", False) _

}

Page 27: Introduction to ado.net web forms

27

Customer: Page_Load

The main change to Page_Load is that it only reads from the database the first time the page is loaded (not during PostBack), and the dataset has to be saved in a Session so we can hang onto the original values.

Also notice that the Fill routine has been modified to read only one row of data.

If Not Page.IsPostBack ThencmpMain.FillCustomer(DsCustomer1, "1")Session("dsCustomer1") = DsCustomer1Page.DataBind()

ElseDsCustomer1 = CType(Session("dsCustomer1"), dsCustomer)

End If

Page 28: Introduction to ado.net web forms

28

Customer: btnSave Saving the data is now handled by the generic routines. Add the

following code to the btnSave_Click routine:

The first routine copies the data from the form to the dataset (using the aryColumns mapping).

The second routine does the update, and checks for concurrency. What happens if there is a concurrency collision? Try it. Where are the underlying values stored? They are kept as properties

within the dataset table. The routine re-reads the database, and replaces the underlying values

with the new current values. However, it leaves this user’s changes on the form. So clicking Save a second time will force update the database if there was a concurrency error.

You really need to add some message and probably more choices to the user. But that is a user interface decision.

tmf.CopyFormToDataSet(Me, aryColumns, DsCustomer1, "Customer", 0)lblMessage.Text = cmpMain.UpdateCustomer(DsCustomer1)

Page 29: Introduction to ado.net web forms

29

Customer: State DropDownList

To provide a drop down list (selection box) for states, you first need to create a table of StateCodes, with the state and the name. Users will see the names (alphabetized), and the two-letter state code will be inserted into the database.

Second, create a new data adapter and dataset. Retreive StateCode and Name, sorted. Deselect the build update. Create the FillStateCodes routine.

Customer form, delete the existing state text box Add the StateCodes data set, then add a DDL and set its tab index ID ddlState DataSource DsStateCodes1 DataMember StateCodes DataTextField: Name DataValueField State In the aryColumns array, change the control type to “DDL” and ID to ddlState In Page_Load, fill the new dataset

cmpMain.FillStateCodes(DsStateCodes1)

Page 30: Introduction to ado.net web forms

30

DDL: Tricky TMF

Microsoft did not bother to create a simple mechanism to get drop down lists to display the currently assigned value. For instance, if the database state value is CT, you want the box to start with a display of Connecticut.

So, turn to the trusty TMF class for help. In properties for the DDL, click the Data Bindings button. Make sure you choose the SelectedIndex on the left side! Choose custom binding, and add: (It’s that easy, see next slide)

tmf.SelectDefaultDDL(sender, DsStateCodes1, DataBinder.Eval(DsCustomer1, "Tables[Customer].DefaultView.[0].State"))

Dataset name that holds the DDL listDataset name for the overall formColumn name from the overall form that holds the default valueTable name for the overall form

Page 31: Introduction to ado.net web forms

31

DDL Binding for SelectedIndex

Page 32: Introduction to ado.net web forms

32

Customer Form

Page 33: Introduction to ado.net web forms

33

The Form is Still not Usable

The generic code can be used for any form. The aryColumns array is the key to providing the information the subroutines need.

You really need to think about a user interface to explain how to handle concurrency collisions. The grid code (later) shows one way to handle the problem. But feel free to experiment, there are no great solutions yet.

Several steps remain to make this a useful form. Selecting a customer/row (tricky, depends on user interface goals) Finding a customer (moderately tricky code) Adding a new customer (relatively easy) Deleting a customer (easy, until you have to show the next customer) Security (relatively easy, but requires more forms) More?

Page 34: Introduction to ado.net web forms

34

Concurrency How does the update command handle optimistic concurrency?

The SQL command uses the original value for each column in its Where clause.

But where does it get (and store) the original value, which is the value that existed when the data row was retrieved?

Answer: the data row holds multiple versions of each data column. You can access them with DataRowVersion enumeration.

If there is a concurrency problem, the BatchUpdate routine retrieves the current value and places it into the “Original” value. It leaves the current user’s value as the primary/current value. You can compare these values in each column to see where the problem was and show both values.

‘ Set ID= the primary key value of the row being editedDim dsRow As DataRow = DsMine1.Tables(“MyTable”).Rows.Find(ID)‘ Check each column/loopIf (dsRow(j) <> dsRow(j, DataRowVersion.Original)) Then

‘ Display concurrency error/valueEnd If

Page 35: Introduction to ado.net web forms

35

Customer: Add Code

Public Function AddCustomer(ByVal ds As DataSet) As String Dim cID As Integer = GenKey("Customer") Dim strMsg As String If (cID < 0) Then strMsg = "Unable to generate a new Customer ID." End If Dim dr As DataRow = ds.Tables("Customer").NewRow() dr("CustomerID") = cID ds.Tables("Customer").Rows.Add(dr) strMsg &= UpdateCustomer(ds, cID) ds.Clear() ' Clear the data set and reload just the one new row ds.AcceptChanges() ' Need to tell it not to delete the original row FillCustomer(ds, cID) Return strMsgEnd Function

GenKey is another generic routine you need to add to your DBMain. If you are running under Oracle, rewrite GenKey to use Sequences.

Page 36: Introduction to ado.net web forms

36

Customer: Delete Code

The Delete code is much trickier, because we need to guess which CustomerID to display next, and bad things happen to the form if we delete all of the rows in the dataset.

Public Function DeleteCustomer(ByVal ds As DataSet) As String Dim sID As String = ds.Tables("Customer").Rows(0)("CustomerID") Dim strMsg As String ' The hard part: What customer do I load next? ' Try finding just the first customer sorted by ID Dim rdr As OleDb.OleDbDataReader Dim cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand() cmd.CommandText = "SELECT CustomerID FROM Customer ORDER BY CustomerID" cmd.Connection = Me.cnnOleSimple cnnOleSimple.Open() Dim cID As Integer

Page 37: Introduction to ado.net web forms

37

Customer: Delete Code 2

Try rdr = cmd.ExecuteReader(CommandBehavior.Default) rdr.Read() cID = CType(rdr("CustomerID"), Integer) If (cID = CType(sID, Integer)) Then ' If delete 1st one, try to get the next row rdr.Read() cID = rdr("CustomerID") End If rdr.Close() Catch e2 As Exception cID = -1 strMsg = "No customers remain. Please add at least one." End Try cnnOleSimple.Close()

Page 38: Introduction to ado.net web forms

38

Customer: Delete Code 3

Try ds.Tables("Customer").Rows(0).Delete() If (cID <> -1) Then UpdateCustomer(ds, cID.ToString) Else UpdateCustomer(ds, Nothing) End If strMsg &= "Deleted customer " & sID

Catch e As Exception strMsg = "Error deleting customer. " & e.Message End Try If (cID = -1) Then ' Dataset can never be empty or form will crash Dim dr As DataRow = ds.Tables("Customer").NewRow dr("CustomerID") = -1 ds.Tables("Customer").Rows.Add(dr) End If Return strMsgEnd Function

Page 39: Introduction to ado.net web forms

39

Summary

The form is getting closer. It still needs to be within an application, that can handle things like

selecting a customer and security. But, building several forms of this type for an application is still

going to be painful, with lots of repetition. Ultimately, it would be nicer if a data wizard existed to build most of

the generic code automatically. Lacking the time to write such a wizard, the next best step is to

create a set of generic templates, that can be copied and used to quickly build forms that handle standard problems.

Page 40: Introduction to ado.net web forms

40


Recommended