Windows and Web Apps in C#
Session 4
Last Update: 4/11
David Figge
dfigge@uw.edu
Page 1
Copyright (C) 2010 by David Figge. All Rights Reserved.
Checkbook Register

Let’s take a look at my solution for the
Checkbook Register program…
Last Update: 4/11
Page 2
Copyright (C) 2010 by David Figge. All Rights Reserved.
Windows Forms

We’re now going to work together to migrate
your program to a Windows Forms project



Together we will





The console app was getting pretty lame
And it will give you a very (very) basic introduction
to Windows forms.
Create a new WinForm project
Move the key class files into it
Add some Windows controls
Create some code and move some existing code
from the main program into the new program’s
form constructor.
Ready to begin?
Last Update: 4/11
Page 3
Copyright (C) 2010 by David Figge. All Rights Reserved.
Windows Forms

Work with the instructor to:


Create a new WinForm app WinCheckbook
Move the BankAccount, Trans, and Transactions classes to the
new project



Add some label controls to the form to display the owner, acct
number, and initial balance
Add a ListView to display the transactions



You’ll need to update the Namespace reference
Put the control into Detail view
Add the column headers Date, Type, Check#, Payee, Amount, and
Balance
In the Form1.cs file


Add a BankAccount object and initialize it
In the Form constructor





Last Update: 4/11
Set the text in the label’s text properties
Copy over the display loop from the original program, modify it
Create an array of string objects containing the fields to display
Create a ListViewItem object, initializing it to the string array
Add it to the ListView object.
Page 4
Copyright (C) 2010 by David Figge. All Rights Reserved.
Basic File I/O
Windows and Web Apps in C#
Last Update: 4/11
Page 5
Copyright (C) 2010 by David Figge. All Rights Reserved.
Components of Simple File I/O

Information-based Functions







I/O Basics
FileInfo
Using Stream I/O
Using Binary I/O
Serializing Data
DirectoryInfo / Directory
DriveInfo
Last Update: 4/11
Page 6
Copyright (C) 2010 by David Figge. All Rights Reserved.
C# I/O Overview

I/O in C# is based on the concept of a
Stream




Streams represent a flow of bytes to or
from an external source (file, pipe, serial
port, etc.)
Streams represent the lowest level of
unformatted data
To use the data, you must format it in
some way
This is done by adding one or more
“adapters” to translate the stream into
something useful…
Last Update: 4/11
Page 7
Copyright (C) 2010 by David Figge. All Rights Reserved.
Using Streams
Sometimes we want additional
C# uses its FileStream classes
functionality, such as buffering
To start with, we use
the low-level
Remember,
although
to
communicate
with
byteIf
the
file
contains
binary
(where data can gather before
it is
FileStream
object we’ve
to readbeen
fromtalking
the about
oriented
I/O
systems.
For
a athe
processed) C# allows you tofile.
addThis data,
takesinstead
thedata
dataof
from
filethis can
from
disk,
example,
let’s
say
we
want
StreamReader
wefrom
attach
additional adapters as you go,
andsuch
translates
it into
bytes.
be data
just about
information
from
a
disk
file.
a
BinaryReader.
We
can
as the BufferedStream object.
anywhere, including
then readmemory
the data(with
as a
ints, floats,
etc.
MemoryStream
object).
Int()R
The
Program
StreamReader
StreamWriter
BinaryReader
Buffered
37 1A Stream 37 1A
F3 D1
F3 D1
File Input
Stream
101010
Disk
For writing We
data,
C# has
could
use it as bytes alone, but it makes
“writer” versions
of each
more sense
to use a higher-level filter to
of the “readers”
to it into something useful. The
translate
translate from
program- class takes low-level byte
StreamReader
As you might expect, to instantiate a
oriented data
to
bits
and
streams and translates
them
to
streamalright
Doin’
“adapter”,
so Strings.
far?you pass in a reference
bytes.
to a lower-level stream object (or another
higher-level stream object).
Last Update: 4/11
Page 8
Copyright (C) 2010 by David Figge. All Rights Reserved.
Common Stream “Adapters”

Base Stream objects

FileStream – Initial access object




MemoryStream – Initial access object


Used to open files
Supports random access
Data is presented as a stream of bytes
Allows you to treat memory as a stream of bytes
Common “Adapters”



StreamReader/Writer – Used for text
BinaryReader/Writer – Used for binary
BufferedStream – Adds buffering support
Last Update: 4/11
Page 9
Copyright (C) 2010 by David Figge. All Rights Reserved.
Text, Unicode, and UTF


As we’ve discussed, C# uses Unicode
for all characters
C# uses its Reader and Writer classes to
convert between Unicode and the
target device

For example ,storing characters in ASCII in
text files
Last Update: 4/11
Page 10
Copyright (C) 2010 by David Figge. All Rights Reserved.
File I/O Example

Watch as I create a very simple console app that
writes the numbers 1-25 to the disk

Steps:

Create a FileStream object






Attach a StreamWriter object
Write the data to the StreamWriter object
Close the StreamWriter object (flushes data to disk)
Close the file
When using Readers, Writers, you can open file
through them (the FileStream is automatic)


Use FileMode.Create, opens file automatically
Remove the FileStream object
The Using statement can close streams for us

Last Update: 4/11
Add the Using statement for FileStream, StreamWriter
(closes them automatically)
Page 11
Copyright (C) 2010 by David Figge. All Rights Reserved.
Your Turn!

Add an Export button to our Checkbook
program


Add a button to the window, which will export
all the transactions onto the disk, to the file
Transactions.csv, one line per transaction
Steps:



Add the Export button, and in the handler
Use a StreamWriter to write the file
Write a line representing the column titles


“Date,Type,Check#,Payee,Amount”
For each of the transactions, write a line containing
all five of the elements separated by commas


This makes a Comma-Separated Variables, or CSV file
This is a common way of exchanging data, and creates a
file that can be read in and understood by Excel (Try it!)
30 Minutes
Last Update: 4/11
Page 12
Copyright (C) 2010 by David Figge. All Rights Reserved.
The File Class

The FileInfo class describes a file or directory
on the disk




It does not directly open the file, rather it
contains the directory-based information about
the file
Generally, you create a File object for each file or
directory you wish to work with on the disk
Note that constructing a File object does not
involve any interaction with the disk. It simply
encapsulates an existing (or soon to exist)
filename into an object
The File class provides several methods to help
you work with and manipulate the file or
directory…
Last Update: 4/11
Page 13
Copyright (C) 2010 by David Figge. All Rights Reserved.
FileInfo Class Details

Constructor:


Properties (typically no interaction with the disk):








boolean Exists – checks to see if File (i.e. name in obj) exists
String FullPath– returns full path to File
String Name – returns name portion of File
String Extension – returns the extension of the file
Long Length – returns the size of the file
Bool IsReadOnly – True if file is read only
String DirectoryName – returns full path of parent directory
Methods (may interact with disk)


File(String pathname)
CopyTo, MoveTo, Delete
Can also use to open the file


FileStream: Open, OpenRead, OpenWrite, Create
StreamReader/Writer: OpenText, CreateText
Last Update: 4/11
Page 14
Copyright (C) 2010 by David Figge. All Rights Reserved.
The DirectoryInfo Class

What FileInfo does for files,
DirectoryInfo does for directories


Allows you to get information on
directories, get lists of files and directories
within it, etc.
Properties:


Exists, Name, FullName, Parent
Methods

Last Update: 4/11
Create, Delete, MoveTo,
DirectoryInfo[] GetDirectories,
FileInfo[] GetFiles
Page 15
Copyright (C) 2010 by David Figge. All Rights Reserved.
File Example
static void Main(string[] args)
{
DirectoryInfo dir = new DirectoryInfo(args[0]);
FileInfo[] files = dir.GetFiles();
DirectoryInfo[] dirs = dir.GetDirectories();
foreach (DirectoryInfo di in dirs)
Console.WriteLine("[" + di.Name + "]");
foreach (FileInfo fi in files)
Console.WriteLine(fi.Name);
Console.WriteLine("\nNumber of directories: {0}", dirs.Length);
Console.WriteLine("Number of Files: {0}", files.Length);
}
This example uses the File object to list and count subdirectories
and files. It uses the GetFiles() and GetDirectories(), and is a
good example of what can be done with the FileInfo and
DirectoryInfo objects.
Last Update: 4/11
Page 16
Copyright (C) 2010 by David Figge. All Rights Reserved.
Recursion


In preparation for the next exercise, I
want to discuss Recursion
A recursive function is a function that –
somewhere in its code – calls itself



C# allows this
The only requirement is that (somewhere)
the function must know when to stop
calling itself and returning
Let’s look at an example…
Last Update: 4/11
Page 17
Copyright (C) 2010 by David Figge. All Rights Reserved.
Recursive Function Example
static void Main(string[] args)
{
int fac = factorial(5); // 1*2*3*4*5, or 120
}
int factorial(int n)
{
if (n == 1) return 1;
else return n * factorial(n-1);
}
Last Update: 4/11
Page 18
Copyright (C) 2010 by David Figge. All Rights Reserved.
Recursion

You do have to be careful with recursion



Due to repeated function calls, recursive calls
that get “out of control” usually result in a
stack error
However, there are times when it is just the
“perfect solution”
You should avoid using this for items where
you may make recursive calls more than 100
or so levels deep


There are usually other non-recursive ways to deal
with situations that are deeper or whose depth is
unknown…
Now for that exercise I promised…
Last Update: 4/11
Page 19
Copyright (C) 2010 by David Figge. All Rights Reserved.
FindFile Lab





We’re going to create a console app file find utility called
FindFile. It will allow you to experiment with FileInfo and
DirectoryInfo a bit and to learn how useful they are
Its syntax will be simple: findfile [filespec] [/r]
FindFile *.txt will display all the files with .txt extensions in the
current directory
FindFile *.txt /r
will recurse subdirectories as well,
displaying all .txt
files located ‘below’
the current directory
as well.
You’ll make this work with the FileInfo and DirectoryInfo
classes…
Last Update: 4/11
Page 20
Copyright (C) 2010 by David Figge. All Rights Reserved.
Supporting Recursion


To support recursion, you might design your program thus:
 In the main function, parse out the command line parameters,
saving the filespec and set a flag indicating if you are recursing or
not
Have the main function call a FindFiles function
 This function uses dirInfo.GetFiles() to find and print all filenames
matching the spec (you can pass in the filespec)
 Then (if recursing directories) use dirInfo.GetDirectories() go
through all the directories
 For each directory
 Use Directory.SetCurrentDirectory to move into the directory
 Call FindFiles recursively to display the files in that directory
and recurse it’s subdirectories
 use Directory.SetCurrentDirectory(“..”) to move back to the
current directory and move to the next in line



Remember to count the files, and to print the relative
path (from the current directory) with the filename.
After you return to the main function, print the number of files found.
To test, in Project Properties/Debug, set the command line arguments
to “*.jpg /r” and the starting directory to the Pictures directory.
60 Minutes
Last Update: 4/11
Page 21
Copyright (C) 2010 by David Figge. All Rights Reserved.
An Introduction to ADO.Net
Windows and Web Apps in C#
Last Update: 4/11
Page 22
Copyright (C) 2010 by David Figge. All Rights Reserved.
Introduction to ADO.Net


ADO.Net is the .Net framework that
supports data access, typically to a
database
ADO isolates the program from the
actual datastore, allowing you to
change back-end database systems
with minimal changes to the code.
Last Update: 4/11
Page 23
Copyright (C) 2010 by David Figge. All Rights Reserved.
ADO Components


ADO has 4 primary objects
Object Type
Base class
Purpose
Connection
DbConnection
Provides connection to a data store, and provide support for
transactions
Command
DbCommand
Programmatically represents a SQL query or stored
procedure.
DataReader
DbDataReader
Provides a forward-only, read-only access to data using a
server-side cursor.
DataAdapter
DbDataAdapter
Transfers DataSets from the database, providing an inmemory version of the table.
Process:
1.
2.
3.
Open connect to DB using Connection object
Create a (SQL) command to execute against the data
Use either


DataReader to read one-line at a time, or
Use a DataAdapter to get an in-memory table of results
Doing okay so far?
Last Update: 4/11
Page 24
Copyright (C) 2010 by David Figge. All Rights Reserved.
ADO Data Providers


Microsoft supplies drivers to support all
(compatible) systems, with a couple of
specialized versions.
Data Provider
Description
ODBC
Provides legacy support for early databases (pre 2000). Most databases
support ODBC, but it is not as efficient as OleDb
OleDb
Microsoft’s generic driver that supports all relatively recent database systems
SQL
Microsoft’s driver to support SQL Server (7.0+). Provides optimizations
specifically for SQL Server
Oracle
Microsoft’s driver to support Oracle, providing optimizations for that platform
This Data Provider is currently marked Obsolete, as Oracle has provided one of
it’s own for .Net 4.0+ (available from the Oracle web site)
Although we will use SQL in our
exercises, you could just as easily use
OleDb.
Last Update: 4/11
Page 25
Copyright (C) 2010 by David Figge. All Rights Reserved.
Simple Data Access

To execute a SQL command:
1.
Create and open a Connection object
establishing a virtual connection to the
database

2.
3.
4.
5.

This requires a connection string
Create a Command object that contains
the SQL statement to execute
Execute the command
If the command returns data, consume it
Close the connection
Let’s talk about each of these in turn…
Last Update: 4/11
Page 26
Copyright (C) 2010 by David Figge. All Rights Reserved.
Creating the Connection
This connection
is defined
through a
To establish
a connection
to a database,
“Connection
There
are several
we use the String”.
Connection
object
(in thisways to
get thiscase
(which
we’ll discuss object).
in a few minutes…).
a SqlConnection
void ReadData()
You can
alsois pass this string in to a constructor.
Once the connection
string
{
SqlConnection
conn =Tonew
SqlConnection();
execute
a SQLthe
command, we create a
established,
we
can
open
And
SQL command
conn.ConnectionString
= @"Data
Source=.\SQLEXPRESS;”+
Command
object.
Thethe
command
object you wish to
connection.
TheCatalog=PersonnelDB;Integrated
connection object (soneeds
it knows
execute.
again, both these
”Initial
Security=True";
to
know…Once
conn.Open();
where to execute the command)…
properties
set can
viathe
ajust
constructor
As
you
readready
thecan
data,
you
use the
Now
we’re
tobe
execute
command.
takes as
them
as parameters.
column
an
index
into
the a
The .Read() method returnsThe
true
ifthat
it name
ExecuteReader
command
returns
SqlCommand cmd = new SqlCommand();
DataReader
object,(the
which
returns to you
was able to=read
the next row.
Queryingobject
DataReader
forward-only,
readcmd.Connection
conn;
thegets
contents
of the column
(pretty
cool!).
the DataReader
object First,Last,Title,Phone
now
the method
cmd.CommandText
= "SELECT
FROM
Employees";
only
of reading
data)
newly read data. You must cast the data because Reader
SqlDataReader reader = cmd.ExecuteReader();
sees everything as an Object
while (reader.Read())
{
Console.WriteLine("Name: {0}",(string)reader["Last“]);
Console.WriteLine("
Title: {0}",(string)reader["Title"]);
Console.WriteLine("
Phone: {0}",(string)reader["Phone"]);
Console.WriteLine("-----------------------------------------");
}
conn.Close();
}
Last Update: 4/11
When you’re all done, you close the
connection.
Page 27
Copyright (C) 2010 by David Figge. All Rights Reserved.
Creating the Connection
void ReadData()
{
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = @"Data Source=.\SQLEXPRESS;”+
”Initial Catalog=PersonnelDB;Integrated Security=True";
Note that, like most Open/Close system
conn.Open();
components, making use of the USING statement is
SqlCommand cmd = new SqlCommand();
better than manually closing the connection (in this
cmd.Connection = conn;
case the conn.Close() function is ALWAYS called,
cmd.CommandText = "SELECT First,Last,Title,Phone FROM Employees";
even if an exception occurs). Using the USING
is preferred, and will now the be norm in
SqlDataReader reader = command
cmd.ExecuteReader();
while (reader.Read())
the examples I show.
{
Console.WriteLine("Name: {0}",(string)reader["Last“]);
Console.WriteLine("
Title: {0}",(string)reader["Title"]);
Console.WriteLine("
Phone: {0}",(string)reader["Phone"]);
Console.WriteLine("-----------------------------------------");
}
}
}
Last Update: 4/11
Is this making sense?
Page 28
Copyright (C) 2010 by David Figge. All Rights Reserved.
Checkbook Database


In a moment, you’ll use what we just
discussed to move the our checking
transactions to a new database.
But first, let’s work together to


Create the CheckbookRegister database
Create a BankAccount table and fill it with the
(non-transaction) data from BankAccount


Insert into BankAccount(InitBal,Name,Acct)
values (“+bal+”,”+Name+”,”+Acct+”)”
Create the Transactions table

Include AcctNum and establish it as a foreign key
relationship to BankAccount.

Last Update: 4/11
This allows you to support multiple bank accounts, and is
a more flexible (and proper) design.
Page 29
Copyright (C) 2010 by David Figge. All Rights Reserved.
Checkbook Database: Your Turn!

Modify the checkbook program by

Modify your LoadTransactions function to move
the existing transaction data into the
Transactions table


Once that worked (once)



Call this method only once, or you will duplicate your
transactions!
Modify the main program to call the BankAccount
default constructor (which doesn’t exist yet)
Create the default (no parameter) BankAccount
constructor that reads the transaction data from the
database instead of from the AcctTransactions object
Good Luck!
45 Minutes
Last Update: 4/11
Page 30
Copyright (C) 2010 by David Figge. All Rights Reserved.
Parameters

Up to now, we’ve been building our SQL
statements by combining text


We did this because it was intuitive and easy
However, it’s not a good practice, as it can be
a security hole


Parameters are a better solution


Especially if you have statements based on user
input
These are very similar to the parameters we use in
function calls, although the syntax is different.
Let’s see an example of a Select statement
without and with parameters…
Last Update: 4/11
Page 31
Copyright (C) 2010 by David Figge. All Rights Reserved.
Parameters
// Without Parameters
cmd.CommandText = “SELECT First,Last,Title,Phone “
“FROM Employees WHERE Title = “ + tbSearch.Text;
+
// With Parameters
This is
called
SQL Injection,
However,First,Last,Title,Phone
what
the
developer
may notand“is a+real
cmd.CommandText = “SELECT
concern.
Parameters
are the best defense
This is how
oneconsidered
might
put together
have
is that, bya simply
“FROM Employees WHERE
Title
=
@Title”;
to
SQL
Injection,
as it
limits
the parameter
select statement
without
parameters.
Itthe
appending
the
text
they typed,
user
cmd.Parameters.AddWithValue(“@Title”,tbSearch.Text);
text
to the
place
innot
the query (in this case
looks reasonable,
and
would
has the
ability
toprobably
add
additional
the
text
for
Where clause).
cause information
any problems
most
toin
that
textcases.
andthe
potentially
access (or damage) sensitive data.
A good rule-of-thumb is to use
This is the same query parameters
using a parameter
whenever using data input by
(you can have as many parameters
as you when inserting data
users (security),
wish). It’s not significantly
more work, and to avoid “quoting
(performance),
and also produces faster execution
within quotes” (readability).
(because the SQL engine doesn’t have to
work as hard to parse the statement).
Do parameters
make sense?
Last Update: 4/11
Page 32
Copyright (C) 2010 by David Figge. All Rights Reserved.
Stored Procedures

Stored Procedures are “functions” (a
series of SQL statements) that are precompiled and stored within the database


Because they’re pre-compiled, they are faster
than ad-hoc SQL statements
Let’s work together to


Create a stored procedure that returns the
BankAccount customer’s name, account
number, and initial balance
Modify our BankAccount constructor to use
that function…
Last Update: 4/11
Page 33
Copyright (C) 2010 by David Figge. All Rights Reserved.
The Disconnected Layer
Windows and Web Apps in C#
Last Update: 4/11
Page 34
Copyright (C) 2010 by David Figge. All Rights Reserved.
The Disconnected Layer

Up to now, we’ve been working in
ADO’s “Connected” layer



Everything we’ve been doing interacts
through a direct connection to the
database
For example, the Reader object uses a
(server side) cursor to retrieve the next
row
ADO also provides a “Disconnected”
layer, allowing you to simulate the
database design in memory
Last Update: 4/11
Page 35
Copyright (C) 2010 by David Figge. All Rights Reserved.
Disconnected Layer Components
DataSet
DataColumn
D
a
t
a
R
o
w
DataTable
DataRelation
The
DataColumn
represents
a database
column
field).have
The something
DataColumn
Of
course,
a table with
columns
is not very
useful(record
if you don’t
to
The
Of
The
Not
As
course,
The
DataSet
DataTable
surprisingly,
the
final
Disconnected
databases
missing
also
element,
has
you
element
many
often
put
Layer
representing
multiple
properties
consist
is
is
the
intended
of
DataColumns
DataRelation
multiple
and
the
to
methods.
database
simulate
tables.
element.
together
table,
We’ll
a
When
database
hit
by
It
has
you
also
putting
those
several
do,
in
resides
memory,
a
you
them
little
properties
can
in
later
into
the
place
an
aas
has many
useful
The
key ones
DataType,
represent
the
rowsproperties.
of data. This
is done
withare
theColumnName,
DataRows element.
We’lland
take
DataSet,
them
designed
and
all into
istoused
asupport
obvious
DataSet
to define
common
that.
place
element,
foreign
Key
to DataTable
ones
start
well.
which
key
is
are
the
relationships
represents
PrimaryKey
object.
DataColumn.
the
between
and
Database
TableName.
DataTables.
level.
Default
Value.
more about
DataRows
in a minute.
Last Update: 4/11
Page 36
Copyright (C) 2010 by David Figge. All Rights Reserved.
Component Summary
Element
Represents
Comments
DataSet
The Database
Holds the high-level design aspects
simulating a database
DataTable
Database Table
Contains the relationships and
settings associated with tables in
database systems
DataRelation
Table Relationships
Represents key relationships
between tables
DataColumn
Table column
Represents a record field
DataRow
A row of data in a table
Contains the row data
Last Update: 4/11
Page 37
Copyright (C) 2010 by David Figge. All Rights Reserved.
Manually Defining a DataSet



Sometimes it’s useful to create a
DataSet, along with all the tables and
relationships, manually
It would also give us an opportunity to
discuss the key elements of these
elements
We can look at our CheckRegister
database as an example…
Last Update: 4/11
Page 38
Copyright (C) 2010 by David Figge. All Rights Reserved.
The DataSet
DataSet bads = new DataSet("Bank Account");
The Account table has 3
columns, so we ‘ll create 3
DataColumn objects to
Info");
represent them.
DataTable AcctTable = new DataTable("Account
DataTable TransTable = new DataTable("Transaction Info");
by creating the DataSet typeof(string));
DataColumn BAAcctNum We’ll
= newstart
DataColumn("AccountNum",
BAAcctNum.AllowDBNull
= false;
element.
We’ll call it “Bank Account”. This
BAAcctNum.Unique = true;
We then
theitDataTable
is just a descriptive
namecreate
we give
in
elements,
oneitsfor
Account
case anything wants
to display
name.
DataColumn BAAcctName = new DataColumn("AccountName", typeof(string));
information
one for
Transaction
The
Accountand
Number
doesn’t
allow
BAAcctName.AllowDBNull = false;
information
Nulls, and must
be unique (it’s the
I mentioned
that the=AcctNum
is the table’s primary key). typeof(decimal));
DataColumn
BAInitBal
new DataColumn("InitialBalance",
BAInitBal.AllowDBNull
primary key for the table.
= false;
A DataTable
allows a primary key that is composed ofFinally, add the tables to the DataSet, and
After
we define
the
AcctTable.Columns.Add(BAAcctNum);
one or more columns. In this case, there’s we can
Thethen
Account
Name
andcolumns,
Initial we
define
the
relationship
AcctTable.Columns.Add(BAAcctName);
then
add them
to the
Columns
only
one,
the
0
entry
in
the
collection.
Balance
columns
aren’t
allowed
between
the
two
tables
like
this,
stating
AcctTable.Columns.Add(BAInitBal);
collection
of
the table like this.
to
be
Null.
...
that
the
AccountNum
columns
in both
You would see very similar logic for
AcctTable.PrimaryKey = new DataColumn[] { AcctTable.Columns[0]
creating the columns and addingtables
them are
to related. };
bads.Tables.Add(AcctTable);
the TransTable.
bads.Relations.Add(new DataRelation("AcctTrans",
AcctTable.Columns[0],
How are we doing?
TransTable.Columns[1]));
Last Update: 4/11
Page 39
Copyright (C) 2010 by David Figge. All Rights Reserved.
Adding a New Row
DataRow acctinfo = AcctTable.NewRow();
acctinfo["AccountNum"] = "93844934";
acctinfo["AccountName"] = "John Doe";You don’t just call the default
DataRow constructor, because
acctinfo["InitialBalance"] = 800;
the row would have no idea of
the columns within the table.
Once you have a row
AcctTable.Rows.Add(acctinfo);
youryou
data
in place,
SoOnce
instead
askisthe
table to
(patterned after the
youyou
then
add row
it tobased
the on
create
a new
columns), you can then add
existing
rowThis
collection
its
columns.
is donelike
with
data similar to how you
this. method.
the NewRow()
read data before.
Now let’s look at how to
add a row of data to an
existing DataTable.
Still making sense?
Last Update: 4/11
Page 40
Copyright (C) 2010 by David Figge. All Rights Reserved.
DataTableReader dtr = TransTable.CreateDataReader();
while (dtr.Read())
{
Console.WriteLine("Payee: {0}", (string)dtr["Payee”]);
...
Reading table data was made similar to
}
Tables also
support simple
queries
like this one. It returns to you
standard
DataReaders.
Startto
bythe
creating
Also, because
references
actual rows are returned, you can
an array of DataRows,
which
youusing
can then navigate through .
a DataTableReader
from
the
table
also make changes
to the
result
set that
willjust
change
in the tables.
Then
go
through
the
its method CreateDataReader.
...
rows like you would a
normal DataReader.
// Select all purchases from QFC
DataRow[] qfcs = TransTable.Select("Payee = 'QFC'");
Decimal total = 0;
foreach(DataRow d in qfcs)
total += d["Amount"];
Still holding on?
Last Update: 4/11
Page 41
Copyright (C) 2010 by David Figge. All Rights Reserved.
DataAdapters



Now that you understand the basics of
manipulating DataSets, it’s time to talk
DataAdapters
Remember I mentioned this section is
on the Disconnected Layer
That all works because of the
DataAdapter object, working with the
other elements we’ve been discussing
Last Update: 4/11
Page 42
Copyright (C) 2010 by David Figge. All Rights Reserved.
DataAdapters





The DataAdapter is analogous to the
Connection object you’re used to
working with
It works differently, however, because
when you request data it connects, gets
the data, then disconnects.
This allows you to work with your data
without requiring (or being slowed down
by) a connection to the database
You can make changes to the data, and
when the DataAdapter reconnects, your
changes will be applied to the database
It’s all very cool and very magical .
Last Update: 4/11
Page 43
Copyright (C) 2010 by David Figge. All Rights Reserved.
Using DataAdapters

Here are the steps to using DataAdapters. Say
we want to work with all our (fictional)
customer records.

Create a DataSet to hold the result set


Create a new DataAdapter


DataAdapter da = new DataAdapter(
“Select * from Customers”, connectionString);
Fill the DataSet with a new table containing the
results of the query


DataSet ds = new DataSet(“Marketing”);
da.Fill(ds,”Customers”);
The DataAdapter connects, gets the data, puts
it into your DataSet, and disconnects.

You are now free to read and manipulate the
data offline (even though it looks online!)
Last Update: 4/11
Page 44
Copyright (C) 2010 by David Figge. All Rights Reserved.
Time To Play


Let’s quit talking and start doing!
Together let’s


Add a few rows to the BankAccount table
Create a simple console application that




Last Update: 4/11
Creates a DataSet
Creates a DataAdapter
Fills the DataSet with “SELECT * from Accounts”
Iterates through the result set and prints the
record information.
Page 45
Copyright (C) 2010 by David Figge. All Rights Reserved.
Your Turn!

Modify your BankAccount constructor so
it uses DataAdapter(s) and DataSet(s) to


Select the Account record with the correct
account number…now that we’ve added
more records to the Accounts table (then
read in the account number, name, and
initial balance)
Use a DataSet to read in and initialize the
array of transactions.
40 Minutes
Last Update: 4/11
Page 46
Copyright (C) 2010 by David Figge. All Rights Reserved.
Updating the Database


The one aspect of DataAdapters that
we haven’t discussed is the process of
updating the database with changes
you made while in your disconnected
state.
This is done through the da.Update()
method…
Last Update: 4/11
Page 47
Copyright (C) 2010 by David Figge. All Rights Reserved.
The Update Method

When the Update call is made

The DataAdapter examines the RowState
of each row


row.RowState values of Added, Deleted, or
Modified are automatically updated based on
what you do within the row
For each row added, deleted, or modified,
that change is propagated to the
database


Errors updating will trigger an exception
You can also monitor (without exceptions) on
a row-by-row update basis for fine tuned
Questions on
updating.
Disconnected States?
Last Update: 4/11
Page 48
Copyright (C) 2010 by David Figge. All Rights Reserved.
End of Session 4
Windows and Web Apps in C#
Last Update: 4/11
Page 49
Copyright (C) 2010 by David Figge. All Rights Reserved.