Tải bản đầy đủ (.pdf) (50 trang)

Practical Database Programming With Visual C#.NET- P8

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (955.61 KB, 50 trang )


5.19 Query Data Using Runtime Objects to SQL Server Database

373
C. The FindName() function is executed to get the student ’ s photo fi le based on the student ’ s
name. The returned student ’ s image fi le is assigned to the local string variable strName.
D. The user - defi ned method BuildCommand() is called to initialize the fi rst Command object
with the correct Connection, CommandType, and CommandText properties. In order to
execute our stored procedure, the properties should be set as follows:


CommandType = CommandType. StoredProcedure


CommandText = “ dbo.StudentInfo ”



Figure 5.129
Testing result for our second stored procedure.
One point you need to note is that if you are using SQL Server Management Studio
Express to build your database, in some situations, you cannot connect the server to open the
database if you are performing some tasks with the Server Explorer such as creating stored
procedures because your server has been connected and the database is open when you create
stored procedures. An error message would be displayed if you try to do that since this version
only allows one instance of the server to be connected at a time. You have to disconnect that
connection fi rst by rebooting your computer.
The content of the CommandText must be equal to the name of the stored procedure we
developed above.
E. The unique input parameter to the stored procedure dbo.StudentInfo is StudentName,
which will be selected by the user from the student name combobox (ComboName.Text)


as the project runs. This dynamic parameter must be added into the Parameters collection
c05.indd 373c05.indd 373 2/11/2010 2:58:54 PM2/11/2010 2:58:54 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
374

Chapter 5 Data Selection Query with Visual C#.NET
private void cmdSelect_Click(object sender, EventArgs e)
{
string strStudent = "dbo.StudentInfo";
string strStudentCourse = "dbo.StudentCourseInfo";
SqlDataAdapter StudentDataAdapter = new SqlDataAdapter();
SqlDataAdapter StudentCourseDataAdapter = new SqlDataAdapter();
SqlCommand sqlCmdStudent = new SqlCommand();
SqlCommand sqlCmdStudentCourse = new SqlCommand();
DataTable sqlStudentTable = new DataTable();
DataTable sqlStudentCourseTable = new DataTable();
SqlDataReader sqlStudentReader, sqlStudentCourseReader;
string strName = string.Empty;
strName = FindName(ComboName.Text);
if (strName == "No Match")
MessageBox.Show("No Matched Student's Image Found!");
BuildCommand(ref sqlCmdStudent, strStudent);
sqlCmdStudent.Parameters.Add("@StudentName", SqlDbType.Char).Value = ComboName.Text;
StudentDataAdapter.SelectCommand = sqlCmdStudent;
if (ComboMethod.Text == "DataAdapter Method")
{
StudentDataAdapter.Fill(sqlStudentTable);
if (sqlStudentTable.Rows.Count > 0)
FillStudentTextBox(sqlStudentTable);
else

MessageBox
.Show("
No matched student found!");
BuildCommand(ref sqlCmdStudentCourse, strStudentCourse);
sqlCmdStudentCourse.Parameters.Add("@StudentID", SqlDbType.Char).Value = txtID.Text;
StudentCourseDataAdapter.SelectCommand = sqlCmdStudentCourse;
StudentCourseDataAdapter.Fill(sqlStudentCourseTable);
if (sqlStudentCourseTable.Rows.Count > 0)
FillCourseList(sqlStudentCourseTable);
else
MessageBox.Show("No matched course_id found!");

}
else //DataReader Method is selected
{
sqlStudentReader = sqlCmdStudent.ExecuteReader();
if (sqlStudentReader.HasRows == true)
FillStudentReader(sqlStudentReader);
else
MessageBox.Show("No matched student found!");
BuildCommand(ref sqlCmdStudentCourse, strStudentCourse);
sqlCmdStudentCourse.Parameters.Add("@StudentID", SqlDbType.Char).Value = txtID.Text;
StudentCourseDataAdapter.SelectCommand = sqlCmdStudentCourse;
sqlStudentCourseReader = sqlCmdStudentCourse.ExecuteReader();
if (sqlStudentCourseReader.HasRows == true)
FillCourseReader(sqlStudentCourseReader);
else
MessageBox.Show("No matched course_id found!");
sqlStudentReader.Close();
sqlStudentCourseReader.Close();

}
sqlStudentTable.Dispose();
sqlStudentCourseTable.Dispose();
StudentDataAdapter.Dispose();
StudentCourseDataAdapter.Dispose();
sqlCmdStudent.Dispose();
sqlCmdStudentCourse.Dispose();
}
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
SQLSelectRTObject.StudentForm cmdSelect_Click()

Figure 5.130

Coding for the Select button Click method.
c05.indd 374c05.indd 374 2/11/2010 2:58:55 PM2/11/2010 2:58:55 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

375
that is the property of the Command class by using the Add() method before the stored
procedure can be executed. The initialized Command object sqlCmdStudent is assigned
to the SelectCommand property of the DataAdapter to make it ready to be used in the
next step.
F. If the user selected the DataAdapter Method, the Fill() method of the DataAdapter is
called to fi ll the Student table, which actually calls our fi rst stored procedure to fi ll the
Student table.
G. If this calling is successful, the Count property should be greater than 0, which means
that at least one row is fi lled into the Student table, and the user - defi ned method
FillStudentTextBox() is called to fi ll six textboxes in the Student form with six pieces of
retrieved columns from the stored procedure. Otherwise, an error message is displayed if
this fi ll has failed.
H. The user - defi ned method BuildCommand() is called again to initialize our second
Command object sqlCmdStudentCourse. The values to be assigned to the properties of
the Command object are:


CommandType = CommandType. StoredProcedure


CommandText = “ dbo.StudentCourseInfo ”
The content of the CommandText must be equal to the name of the stored procedure we
developed above.

I. The unique input parameter to the stored procedure dbo.StudentCourseInfo is the
StudentID, which is obtained from the calling of the fi rst stored procedure and
stored in the student ID textbox txtID. This dynamic parameter must be added into the
Parameters collection that is the property of the Command class by using the Add()
method before the stored procedure can be executed. The initialized Command object
sqlCmdStudentCourse is assigned to the SelectCommand property of the another
DataAdapter to make it ready to be used in the next step.
J. The Fill() method of the DataAdapter is called to fi ll the StudentCourse table, which calls
our second stored procedure to fi ll the StudentCourse table.
K. If this calling is successful, the Count property should be greater than 0, which means
that at least one row is fi lled into the StudentCourse table, and the user - defi ned method
FillCourseList() is called to fi ll the CourseList box in the Student form with all courses
(course_id) retrieved from the stored procedure. Otherwise, an error message is displayed
if this fi ll has failed.
L. If the user selects the DataReader method, the ExecuteReader() method is called
to retrieve back all information related to the selected student and assign it to the
sqlStudentReader object.
M. If this method is executed successfully, which means that at least one row of data is read
out and assigned to the DataReader, the HasRows property should be true, and the user -
defi ned method FillStudentReader() is executed to fi ll the related information to six
textboxes in the Student form.
N. Otherwise, an error message is displayed to indicate this situation.
O. The BuildCommand() method is called to build the StudentCourse Command object with
our second stored procedure. The unique input parameter to this stored procedure is the
StudentID that is added to the Parameters collection that is a property of the Command
object. The fi nished Command object is assigned to the SelectCommand property of the
StudentCourse DataAdapter.
c05.indd 375c05.indd 375 2/11/2010 2:58:55 PM2/11/2010 2:58:55 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
376


Chapter 5 Data Selection Query with Visual C#.NET
P. The ExecuteReader() method is called to run our second stored procedure to read out all
courses taken by the selected student, and assign them to the StudentCourse DataReader
object.
Q. If the method ExecuteReader() runs successfully, the HasRows property of the DataReader
object should be true, the user - defi ned method FillCourseReader() is executed to fi ll all
courses (course_id) into the CourseList listbox. Otherwise if this method has failed, an
error message is displayed.
R. Two student DataReader objects are released before we can exit this method.
S. The cleaning job is performed to release all other data objects used in this method.
The code for the method FindName() is identical to what we developed for the
same method in Section 5.18.5.2 . Refer to Figure 5.99 to get detailed information for this
coding.
In order to pick up the correct student ’ s image fi le from this subroutine, note that
you must store all students ’ image fi les in the folder in which your Visual C# 2008 pro-
ject ’ s executable fi le is located. In our application, this folder is C:\Book6\Chapter 5\
SQLSelectRTObject\bin\Debug. If you place those students ’ image fi les in another folder,
you must provide a full name, which includes the drive name, path, and the image fi le
name, for that student ’ s image fi le to be accessed, and assign it to the returning string
variable strName in this method. The coding for the BuildCommand() method is shown
in Figure 5.131 .
This coding is straightforward and easy to be understood. First, a new LogInForm
instance is created, and the getLogInForm() method is called to pick up the global con-
nection object and assign it to the Connection property of the Command object. Then
the Command object is initialized by assigning the related properties such as the
CommandType and CommandText to it. The point is that the value assigned to the
CommandType must be StoredProcedure, and the value assigned to the CommandText
must be equal to the name of the stored procedure we developed in the last section.
The codes for the methods FillStudentTextBox(), MapStudentTextBox(), and

FillCourseList() are shown in Figure 5.132 . In total we need six pieces of information for
the selected student, so a six - dimension textbox array StudentTextBox[5] is used (the
index is based on 0).
In the method FillStudentTextBox(), a double foreach loop is used to retrieve each
queried column from the returned row. The outer loop is only executed one time since
we have only retrieved back one data row from the Student table. Each fetched column
is assigned to the associated textbox to be displayed in the Student form. The method
private void BuildCommand(ref SqlCommand cmdObj, string cmdString)
{
LogInForm logForm = new LogInForm();
logForm = logForm.getLogInForm();
cmdObj.Connection = logForm.sqlConnection;
cmdObj.CommandType = CommandType.StoredProcedure;
cmdObj.CommandText = cmdString;
}
SQLSelectRTObject.StudentForm BuildCommand()

Figure 5.131
Coding for the BuildCommand method.
c05.indd 376c05.indd 376 2/11/2010 2:58:55 PM2/11/2010 2:58:55 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

377
MapStudentTextBox() is to set up a one - to - one correct relationship between each
element in the textbox array and each associated textbox control in the Student
form. The functionality of the method FillCourseList() is to pick up each matched row
(course_id) from the fi lled StudentCourse table and add them into the CourseList listbox.
The codes for the methods FillStudentReader() and FillCourseReader() are shown in

Figure 5.133 .
In the method FillStudentReader(), fi rst textbox object array is initialized, and then
the MapStudentTextBox() method is executed to set up a correct relationship between
each element in the textbox array and each associated textbox control in the Student
form. A while and a for loop are utilized to pick up each fetched column and assign them
to the associated textbox control. The point is the difference between the system method
GetString() and GetValue() that belong to the DataReader class. The former can be used
to get only string data stored in the database, but the latter can be used to get any kind
of data stored in the database. The issue is that another system method, ToString(), must
be attached to this GetValue() to convert the data from any other data type to the string
and assign it to the Text property of each TextBox control. Therefore, the latter is more
popular and more powerful in a data - driven application. You can try to compare these
two methods yourself if you like.
private void FillStudentTextBox(DataTable StudentTable)
{
int pos1 =0;
for (int pos2 = 0; pos2 <= 6; pos2++) //Initialize the textbox array
StudentTextBox[pos2] = new TextBox();
MapStudentTextBox(StudentTextBox);
foreach (DataRow row in StudentTable.Rows)
{
foreach (DataColumn column in StudentTable.Columns)
{
StudentTextBox[pos1].Text = row[column].ToString();
pos1++;
}
}
}
private void MapStudentTextBox(Object[] sTextBox)
{

sTextBox[0] = txtID; //The order must be identical with the
sTextBox[1] = txtGPA; //order in the query string - strStudent
sTextBox[2] = txtCredits;
sTextBox[3] = txtMajor;
sTextBox[4] = txtSchoolYear;
sTextBox[5] = txtEmail;
}
private void FillCourseList(DataTable StudentCourseTable)
{
CourseList.Items.Clear();
foreach (DataRow row in StudentCourseTable.Rows)
{
CourseList.Items.Add(row[0]); //the 1st column is course_id - strStudentCourse
}
}
SQLSelectRTObject.StudentForm FillStudentTextBox()

Figure 5.132
Coding for three user - defi ned methods.
c05.indd 377c05.indd 377 2/11/2010 2:58:56 PM2/11/2010 2:58:56 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
378

Chapter 5 Data Selection Query with Visual C#.NET
The functionality of the method FillCourseReader() is similar to the method
FillStudentReader(). The only difference between them is that the Add() method is used
to add each fetched row (course_id) to the listbox in the FillCourseReader() method.
We almost completed all coding development for this project. Finally don ’ t forget to
make coding for the Back command button. Enter this.Hide() into this method.
Now we can begin to test calling those two stored procedures from our Visual C#

project. Build the project and click on the Start Debugging button to run our project,
enter user name and password, and select the Student Information item to open the
Student form window, which is shown in Figure 5.134 .
Select Ashly Jade from the Student Name combobox and click on the Select button.
All information related to this student and the courses are displayed in the six textboxes
and the CourseList box, which is shown in Figure 5.134 .
Our calling to two stored procedures are very successful! Some readers may fi nd that
these two stored procedures are relatively simple, and each procedure only contains one
SQL statement. Let ’ s dig a little deeper and develop some sophisticated stored proce-
dures and try to call them from our Visual C# project. Next we will develop a stored
procedure that contains more SQL statements.
5.19.2.7.4 Query Data Using More Complicated Stored Procedures We want to
get all courses (all course_ids) taken by the selected student based on student name from
the StudentCourse table. To do that, we must fi rst go to the Student table to obtain the
associated student_id based on the student name since there is no student name column
available in the StudentCourse table. Then we can go to the StudentCourse table to pick
up all course_id based on the selected student_id. We need to perform two queries to
complete this data - retrieving operation. Now we try to combine these two queries into a
private void FillStudentReader(SqlDataReader StudentReader)
{
int intIndex = 0;
for (int pos2 = 0; pos2 <= 6; pos2++) //Initialize the textbox array
StudentTextBox[pos2] = new TextBox();
MapStudentTextBox(StudentTextBox);
while (StudentReader.Read())
{
for (intIndex = 0; intIndex <= StudentReader.FieldCount - 1; intIndex++)
StudentTextBox[intIndex].Text = StudentReader.GetValue(intIndex).ToString();
}
}

private void FillCourseReader(SqlDataReader StudentCourseReader)
{
int pos = 0;
CourseList.Items.Clear();
while (StudentCourseReader.Read())
{
for (pos = 0; pos <= StudentCourseReader.FieldCount - 1; pos++)
CourseList.Items.Add(StudentCourseReader.GetValue(pos).ToString());
}
}
SQLSelectRTObject.StudentForm FillStudentReader()

Figure 5.133
Coding for another two user - defi ned methods.
c05.indd 378c05.indd 378 2/11/2010 2:58:56 PM2/11/2010 2:58:56 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

379
single stored procedure to simplify our data - querying operation. First let ’ s create our
stored procedure.
Open Visual Studio.NET and open the Server Explorer window; click on the plus
symbol icon that is next to the CSE_DEPT database folder to connect to our database
if this database was added into the Server Explorer before. Otherwise you need to right -
click on the Data Connections folder to add and connect to our database.
Right - click on the Stored Procedures folder and select the Add New Stored Procedure
item to open the Add Procedure dialog box, and then enter the codes shown in Figure
5.135 into this new procedure.


Figure 5.134
Running status of the Student form.

Figure 5.135
New stored procedure: StudentCourseINTO.
c05.indd 379c05.indd 379 2/11/2010 2:58:56 PM2/11/2010 2:58:56 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
380
Chapter 5 Data Selection Query with Visual C#.NET
Let ’ s give a detailed discussion for this piece of coding.
A. The stored procedure is named dbo.StudentCourseINTO.
B. The input parameter is the student name, @stdName, which is a varying - char variable
with the maximum characters of 50. All parameters, no matter input or output, must be
declared inside the braces.
C. The local variable @stdID is used to hold the returned query result from the fi rst SQL
statement that retrieves the student_id.
D. T h e fi rst SQL statement is executed to get the student_id from the Student table based
on the input parameter @stdName. A SET command must be used to assign the returned
result from the fi rst SQL query to the local variable (or intermediate variable) @stdID.
The fi rst SQL statement must be covered by the parenthesis to indicate that this whole
query will be returned as a single data.
E. The second SQL statement is executed, and this query is used to retrieve all courses
(course_id) taken by the selected student from the StudentCourse table based on the
student_id (@stdID) obtained from the fi rst query.
F. Finally the queried result, all courses or course_id, is returned.
Go to File|Save StoredProcedure1 to save this stored procedure.
Now let ’ s test our stored procedure in the Server Explorer window. Right - click on
our new created stored procedure StudentCourseINTO and select the Execute item from
the pop - up menu. On the opened dialog box, enter the student ’ s name, Erica Johnson;
then click on the OK button to run the procedure. The running result is shown in Figure

5.136 .
Figure 5.136
Running result of the stored procedure.
c05.indd 380c05.indd 380 2/11/2010 2:58:58 PM2/11/2010 2:58:58 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

381
Next we need to develop a Visual C# project to call this stored procedure to test the
functionality of the stored procedure. To save time and space, we added a new form
window into this project and named it SPForm.
Open our project SQLSelectRTObject and select Project | Add Windows Form item,
enter SP Form.cs into the Name: box and click on the Add button to add this new form
into our project. Enter “ SPForm ” into the name property as the name for this form.
Enlarge the size of this SP Form by dragging the border of the form window, and
then open the Student form window. We need to copy all controls on the Student form
to our new SP form. On the opened Student form, select Edit|Select All and Edit|Copy
items, and then open the SP form and select Edit|Paste to paste all controls we copied
from the Student form.
To save time, next we need to copy most codes from the Student code window
to our new SP form code window. But fi rst you need to add the SQL Server - related
namespace System.Data.SqlClient to the namespace declaration section on this SP form
code window. The only difference is the codes for the Select button Click method,
cmdSelect_Click(). Don ’ t copy this piece of code since we need to develop new codes to
test our stored procedure later. To copy all other codes, open the code window of the
Student form, select those codes, copy, and then paste them to our new SP form code
window. One point you need to note is that when you copy the codes for two methods,
such as the constructor of the SP Form and the Back button Click, you must fi rst open
the constructor or the Back method in the SP form, and only copy the body of those

methods without including the header and ender of those methods.
Now let ’ s develop the codes for our Select button Click method. Most codes are
identical to those we developed for the Student form, such as the methods FindName()
and FillCourseReader(). Open the Select button Click method by double - clicking on the
Select button from the Designer window, and enter the code shown in Figure 5.137 into
this method. Let ’ s discuss this piece of code step by step to see how it works.
A. The name of our stored procedure, “ dbo.StudentCourseINTO ” , must be declared fi rst,
and this name must be identical with the name we used when we created the stored pro-
cedure in the Server Explorer window.
B. All data components, including the Command, DataAdapter, DataTable, and DataReader
objects, are declared here since we need to use them for this data query operation.
C. The method FindName() is called to get and display the matched student image fi le, and
the returned name of the image fi le is stored in the local string variable strName.
D. The Command object is initialized with suitable properties by executing the user - defi ned
method BuildCommand(). The CommandType property must be StoredProcedure to
indicate that this query is to execute a stored procedure. The CommandText property
must be equal to the name of our stored procedure, “ dbo.StudentCourseINTO ” , which is
stored in a string variable strStudentCourse.
E. The input parameter to the stored procedure is the student name, which is obtained from
the student combobox, and it should be added into the Parameters collection property of
the Command object. You need to note that the nominal name @stdName must be identi-
cal with the input parameter name we defi ned in the parameter braces in our stored
procedure dbo.StudentCourseINTO. The real parameter is entered by the user as the
project runs. The fi nished Command object is assigned to the SelectCommand property
of the DataAdapter, which will be used later to fetch the desired course_id from the
StudentCourse table.
c05.indd 381c05.indd 381 2/11/2010 2:58:59 PM2/11/2010 2:58:59 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
382


Chapter 5 Data Selection Query with Visual C#.NET
F. If the user selected the DataAdapter Method, the Fill() method is called to fi ll the
StudentCourse table with the desired course_id.
G. If the Count property is greater than 0, this fi ll is successful. The user - defi ned method
FillCourseList() is called to fi ll the fetched course_id into the CourseList listbox. Otherwise
an error message is displayed to indicate this situation.
H. If the user selected the DataReader Method, the ExecuteReader() method is executed to
invoke the DataReader to call our stored procedure.
I. If this call is successful, the queried result should be stored in the DataReader with
certain rows. The user - defi ned method FillCourseReader() is executed to fi ll the returned
course_id into the CourseList box in that situation. Otherwise an error message is
displayed if this call is failed.
J. The cleaning job is performed to release all objects used in this data query operation.
Most user - defi ned methods, such as BuildCommand() and FindName(), are identical
with those methods in the Student form without any modifi cation. For your convenience,
we show the other two user - defi ned methods FillCourseList() and FillCourseReader()
again in Figure 5.138 .
private void cmdSelect_Click(object sender, EventArgs e)
{
string strStudentCourse = "dbo.StudentCourseINTO";
SqlDataAdapter StudentCourseDataAdapter = new SqlDataAdapter();
SqlCommand sqlCmdStudentCourse = new SqlCommand();
DataTable sqlStudentCourseTable = new DataTable();
SqlDataReader sqlStudentCourseReader;
string strName = string.Empty;
strName = FindName(ComboName.Text);
if (strName == "No Match")
MessageBox.Show("No Matched Student's Image Found!");
BuildCommand(ref sqlCmdStudentCourse, strStudentCourse);
sqlCmdStudentCourse.Parameters.Add("@stdName", SqlDbType.Char).Value = ComboName.Text;

StudentCourseDataAdapter.SelectCommand = sqlCmdStudentCourse;
if (ComboMethod.Text == "DataAdapter Method")
{
StudentCourseDataAdapter.Fill(sqlStudentCourseTable);
if (sqlStudentCourseTable.Rows.Count > 0)
FillCourseList(sqlStudentCourseTable);
else
MessageBox.Show("No matched course_id found!");
}
else //DataReader Method is selected
{
sqlStudentCourseReader = sqlCmdStudentCourse.ExecuteReader();
if (sqlStudentCourseReader.HasRows == true)
FillCourseReader(sqlStudentCourseReader);
else
MessageBox.Show("No matched course_id found!"
);
sqlStudentCourseReader.Close();
}
sqlStudentCourseTable.Dispose();
StudentCourseDataAdapter.Dispose();
sqlCmdStudentCourse.Dispose();
}
A
B
C
D
E
F
G

H
I
J
SQLSelectRTObject.SPForm cmdSelect_Click()

Figure 5.137
Coding for the Select button Click method.
c05.indd 382c05.indd 382 2/11/2010 2:58:59 PM2/11/2010 2:58:59 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

383
Before you can test this method, you need to perform the following operations
to the Selection form to allow users to select this form. Open the code window of the
Selection form and add the following codes:
1. Create a new fi eld - level instance of the SP Form by entering SPForm spForm = new
SPForm(); inside the SPForm class.
2. Add a new item SP Information into the ComboSelection combobox by entering this.
ComboSelection.Items.Add(“SP Information”); into the constructor of this form.
3. Add a selection branch for the SP Information by entering the following code into the OK
button Click method:
else if (this.ComboSelection.Text == “ SP Information ” )
spForm.Show();
4. Add spForm.Close() into the Exit button Click method.
Now you can run the project to test this stored procedure. One important issue is
that you may encounter a database connection error when you run this project. The
reason for this error is that the SQL Server 2005 Express only allows the user to create
a single instance of the database and allows single connection to this database. In other
words, multiple accessing of this database at the same time is prohibited. Therefore you

need to disconnect the connection you set up before using the Server Explorer by reboot-
ing the computer, and then reopen the project to run it. A possible solution to this
problem is that you can copy the completed database fi le CSE_DEPT.mdf into another
folder in your computer; in our case, it is C:\database folder, and connect your project to
this database fi le using the Server Explorer. You can use the same database fi le CSE_
DEPT.mdf that is located at the default SQL Server 2005 database folder, C:\Program
Files\Microsoft SQL Server 2005\MSSQL.1\MSSQL\Data, as your target database and
connect it to your project using the codes. The prerequisite to use this possible solution
is that two database fi les must be identical, and both fi les are fi nal versions without any
further modifi cation.
private void FillCourseList(DataTable StudentCourseTable)
{
CourseList.Items.Clear();
foreach (DataRow row in StudentCourseTable.Rows)
{
CourseList.Items.Add(row[0]); //the 1st column is course_id - strStudentCourse
}
}
private void FillCourseReader(SqlDataReader StudentCourseReader)
{
int pos = 0;
CourseList.Items.Clear();
while (StudentCourseReader.Read())
{
for (pos = 0; pos <= StudentCourseReader.FieldCount - 1; pos++)
CourseList.Items.Add(StudentCourseReader.GetValue(pos).ToString());
}
}
SQLSelectRTObject.SPForm FillCourseList()


Figure 5.138
Coding for two user - defi ned methods.
c05.indd 383c05.indd 383 2/11/2010 2:58:59 PM2/11/2010 2:58:59 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
384
Chapter 5 Data Selection Query with Visual C#.NET
As the project runs, enter the suitable username and password, and then select the
SP Information from the Selection form to open the SP Form window. Select a student
name from the student combobox and click on the Select button. All courses taken by
the selected student will be displayed in the CourseList box, which is shown in
Figure 5.139 .
The testing result for our stored procedure is very good. Is that correct? The answer
is yes, but we may do a little more to develop a more sophisticated stored procedure to
meet our special requirement. What is our special requirement? We want to develop
some nested stored procedures and call the nested stored procedure from our main or
parent stored procedure. Sounds complicated? Yes, but we try to make this complicated
issue simple with the following example.
5.19.2.7.5 Query Data Using Nested Stored Procedures The so - called nested
stored procedure is very similar to subroutines or subqueries, which means that a main
stored procedure can be considered as a parent stored procedure, and a substored pro-
cedure can be considered as a child stored procedure. The parent stored procedure can
call the child stored procedure as it likes. In this section, we try to create two stored
procedures; one is a main procedure and the other is a child stored procedure. The main
stored procedure, StudentAndCourse, is used to get all courses taken by the selected
student from the StudentCourse table based on the student_id, and the child stored pro-
cedure, StudentInfoID, is used to get the student_id from the Student table based on the
input student name.
Now open the Server Explorer window and connect to our database CSE_DEPT.
After the database is connected, right - click on the Stored Procedures folder and select
the Add New Stored Procedure item to open the Add Procedure dialog box.

First, let ’ s create our main stored procedure — dbo.StudentAndCourse. Enter the
codes shown in Figure 5.140 into our main stored procedure.
Figure 5.139
Running status of calling stored procedure.
c05.indd 384c05.indd 384 2/11/2010 2:58:59 PM2/11/2010 2:58:59 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

385
The functionality of each line of the coding is:
A. The name of the main stored procedure is declared fi rst, which is dbo.StudentAndCourse.
This name must be identical with the name of the stored procedure used in our Visual C#
2008 project later.
B. The input parameter @StudentName is declared here.
C. The local variable @StudentID is used as an output parameter for the child stored proce-
dure that will return this parameter, student_id, to our main procedure.
D. Call the child stored procedure to execute it using the command EXEC. This calling passes
two parameters to the child stored procedure: the input parameter to the child procedure
@StudentName and the output parameter @StudentID. The latter must be indicated with
the keyword OUTPUT. Later in the child stored procedure, you must also declare this
parameter as an output parameter using the keyword OUTPUT to match its defi nition
defi ned in this main stored procedure.
E. After the child stored procedure is executed, it returns the student_id. Now we can
perform our main query to obtain all courses taken by the selected student from the
StudentCourse table based on the student_id returned by the child stored procedure.
F. The retrieved courses are returned to the calling procedure developed in Visual C# 2008.
Click on the File | Save StoredProcedure1 item to save the main stored procedure.
Second, let ’ s create our child stored procedure. Right - click on the Stored Procedures
folder and select the Add New Stored Procedure item from the pop - up menu. On the

opened dialog box, enter the codes shown in Figure 5.141 into this new stored procedure.
The functionality for each coding line is explained below:
A. The name of the child stored procedure is declared fi rst, which is dbo.StudentInfoID. This
name must be identical with the name used by our main stored procedure when this child
procedure is called.
B. Two parameters are declared here: The fi rst one, @sName, is the input, and the second,
@sID, is the output parameter. The default type of parameter is INPUT, so the keyword
OUTPUT must be attached for the second parameter since it is an output and will be
returned to the main stored procedure.

Figure 5.140
Main stored procedure.
c05.indd 385c05.indd 385 2/11/2010 2:59:01 PM2/11/2010 2:59:01 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
386
Chapter 5 Data Selection Query with Visual C#.NET
C. The SQL statement is executed to get the desired student_id from the Student table based
on the input student name. The returned student_id will be assigned to the output param-
eter @sID by using the SET command.
D. The output parameter @sID is returned to the main stored procedure.
Click on the File|Save StoredProcedure1 item to save our child stored procedure.
To test both main and child stored procedure in the Server Explorer window, right -
click on the main stored procedure StudentAndCourse item, and then select Execute
item to open the Run Stored Procedure dialog.
Enter a student name, such as Erica Johnson, and click on the OK button to run both
stored procedures. The running result is shown in Figure 5.142 . Our nested stored pro-
cedures work fi ne!
To call this nested stored procedure, we need to develop a Visual C# 2008 project.
In order to save time and space, you can use the coding we developed for the SPForm
window in the last section. All coding is the same and the only modifi cations are the

stored procedure ’ s name declared in the cmdSelect_Click() method and the nominal
input parameter name to the stored procedure. Change the name of the stored procedure
from “ dbo.StudentCourseINTO ” to “ dbo.StudentAndCourse ” (refer to line A in Figure
5.137 ), and change the nominal parameter ’ s name from “ @stdName ” to “ @StudentName ”
(refer to line E in Figure 5.137 ). Then you can run this project to get the same result,
which is shown in Figure 5.139 , as we got from the last project.
At this point, we fi nished developing the data - driven project using the general real -
time object for the SQL Server database. A complete project named SQLSelectRTObject
can be found in the folder DBProjects\Chapter 5 located at the accompanying ftp site
(see Chapter 1 ).
Now let ’ s go to the next part in this chapter — develop a data - driven application using
the LINQ to SQL with the SQL Server database.
5.19.3 Query Data Using LINQ to SQL Technique
As we discussed in Chapter 4 , LINQ to SQL is an application programming interface
(API) that allows users to easily and conveniently access the SQL Server database from
the Standard Query Operators (SQO) related to the LINQ. To use this API, you must
Figure 5.141
Child stored procedure.
c05.indd 386c05.indd 386 2/11/2010 2:59:02 PM2/11/2010 2:59:02 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

387
fi rst set up a mapping relationship between your relational database and a group of
objects that are instantiated from entity classes. The LINQ to SQL or the Standard Query
Operators will interface to these entity classes to perform the real database operations.
In other words, each entity class can be mapped or is equivalent to a physical data table
in the database, and each entity class ’ s property can be mapped or is equivalent to a data
column in that table. Once this mapping relationship has been set up, one can use the

LINQ to SQL to access and manipulate data against the databases.
After entity classes are created and the mapping relationships between each physical
table and each entity class has been built, the conversion for data operations between the
entity class and the real data table is needed. The class DataContext will function in this
role. Basically, the DataContext is a connection class that is used to establish a connec-
tion between your project and your database. In addition to this connection role, the
DataContext also provides the conversion function to convert or interpret operations of
the Standard Query Operators for the entity classes to the SQL statements that can be
run in real databases.
The procedure to use LINQ to SQL to perform data actions against SQL Server
database can be described in the sequence listed below:
1. Add the System.Data.Linq.dll assembly into the project that will use LINQ to SQL by
adding the reference System.Data.Linq.
2. Create an entity class for each data table by using one of two popular tools: SQLMetal or
Object Relational Designer.
3. Add a connection to the selected database using the DataContext class or the derived class
from the DataContext class.
4. Use LINQ to SQL to access the database to perform desired data actions.

Figure 5.142
Running result of the nested stored procedure.
c05.indd 387c05.indd 387 2/11/2010 2:59:03 PM2/11/2010 2:59:03 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
388
Chapter 5 Data Selection Query with Visual C#.NET
The difference between the SQLMetal and the Object Relational Designer is that
the former is a console - based application but the latter is a window - based application.
This means that the SQLMetal provides a DOS - like template, and the operations are
performed by entering single commands into a black - white window. The Object Relational
Designer provides a graphic user interface (GUI) and allows users to drag - place tables

represented by graphic icons into the GUI. Obviously, the second method or tool is more
convenient and easier compared with the fi rst one.
In this section, we will develop a new sample Visual C# 2008 project named
SQLSelectRTObjectLINQ and use it to illustrate how to perform the data query using
the LINQ to SQL method step by step. Now let ’ s create a new Visual C# project in our
default folder C:\Book6\Chapter 5. For your convenience, a blank project with fi ve form
windows has been created, and you can directly use this blank project to develop your
codes to perform the LINQ to SQL data query. This project, SQLSelectRTObjectLINQ,
is located at the folder DBProjects\Chapter 5 at the accompanying ftp site (see Chapter
1 ), and you can copy and paste it into your folder to use it.
5.19.3.1 Create Entity Classes and Connect DataContext to Database
We have provided a very detailed discussion about the entity classes and DataContext
object as well as how to use the Object Relational Designer to create and add these
components to a data - driven project to perform LINQ to SQL queries in Section 4.6.1 .
Before we can continue to go to the next step, refer to that section to get a clear picture
of how to create and use these components.
5.19.3.2 Query Data Using LINQ to SQL for LogIn Form
When we fi nished reviewing for Section 4.6.1 in Chapter 4 , we can continue to complete
our sample project. First, we need to create a fi eld variable cse_dept based on our derived
DataContext class CSE_DEPTDataContext. As we discussed in the last section, this
object is used to connect to our sample database. Four overloaded constructors are avail-
able for this DataContext class, but in this application we will use the simplest one to
simplify our coding process. Open the code window of the LogInForm and enter the
codes shown in Figure 5.143 into this code section.
Let ’ s look at this piece of code to see how it works.
A. The namespace System.Data.Linq is added into this code section since we need to use all
data components related to LINQ to SQL, and this namespace contains all of them.
B. A new instance of our derived class CSE_DEPTDataContext is created with the fi rst
constructor. A trick here is that no connection string is included in this connection object.
Yes, but where is the connection string? How can we connect to our database without

connection string? However, the connection string is in there. Where? Let ’ s see.
Open the application confi guration fi le named app.confi g located at the Solution
Explorer window by double - clicking on it. A sample fi le is shown in Figure 5.144 .
It can be found from this XML fi le that the connection string is already in there under
the ConnectionString tag, which includes the location of the sample database fi le CSE_
DEPT.mdf. In this application, it is the default folder of the SQL Server 2005 database
fi le, C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data.
c05.indd 388c05.indd 388 2/11/2010 2:59:05 PM2/11/2010 2:59:05 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

389
When you create a new instance of the derived DataContext class to connect to the
sample database, the system can automatically locate this connection string from this
confi guration fi le and use it to do this connection even we did not clearly indicate this
connection string. The instance cse_dept has fi nished the connection when you create it,
and save this connection in this instance when it is created. Now we can use this connec-
tion object to perform the data actions against the database.
Now let ’ s develop the codes for the login process. Since we only deal with this login
process using the LINQ to SQL, we only need one LogIn button in this LogInForm
window. Delete one button from this form window and rename the left button as
cmdLogIn and change its Text property to LogIn.
Double - click on the LogIn button from the form window to open its Click method,
and enter the codes shown in Figure 5.145 into this method.
Let ’ s take a closer look at this piece of code to see how it works.
A. Two local - level string variables, username and password, are created, and these two vari-
ables are used to hold the returned queried data from the LogIn table.
using System;
using System.Collections.Generic;

using System.ComponentModel;
using System.Data;
using System.Data.Linq;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SQLSelectRTObjectLINQ
{
public partial class LogInForm : Form
{
public CSE_DEPTDataContext cse_dept = new CSE_DEPTDataContext();
public LogInForm()
{
InitializeComponent();
}
}
A
B
SQLSelectRTObjectLINQ.LogInForm LogInForm()

Figure 5.143
Coding for the creation of the fi eld variable.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="MSSQLSelectRTObjectLINQ.Properties.Settings.CSE_DEPTConnectionString"
connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=&quot;C:\Program Files

\Microsoft SQL Server\MSSQL.1\MSSQL\Data\CSE_DEPT.mdf&quot;;Integrated
Security=True;Connect Timeout=30;User Instance=False"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>

Figure 5.144
Sample coding for the app.confi g fi le.
c05.indd 389c05.indd 389 2/11/2010 2:59:05 PM2/11/2010 2:59:05 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
390

Chapter 5 Data Selection Query with Visual C#.NET
B. An instance of the next form class SelectionForm, selForm, is created and this form will
be displayed if the login process is completed successfully.
C. As we discussed in the last section when we built the entity classes for this project, all fi ve
entity classes are related or bounded by using the associations (primary - foreign keys).
Also recall that in Chapter 4 we discussed that most normal LINQ queries are performed
on arrays or collections that apply the IEnumerable < T > or IEnumerable interfaces, but
in LINQ to SQL queries, they are performed on entity classes that apply the IQueryable < T >
interface. This means that besides the Standard Query Operators, LINQ to SQL queries
have additional query operators available since IQueryable < T > applies IEnumerable < T > .
Here querying an associated entity class in LINQ to SQL is used with the IQueryable < T >
interface, and the < T > is the type of member variable of the related entity class. In this
case, it is our LogIn table. An iteration variable lg is used to iterate over the result of this
query from the LogIn table. Then a similar SQL SELECT statement is executed with the
WHERE clause. Two criteria are used for this query, user_name and pass_word, and these
two criteria are connected with a logic AND operator. Note the member variable of our
entity class LogIn, which is named LogIns in this query. The relationships or the associa-
tions between the LogIn, Faculty, and Student tables are many - to - one, which means that

many faculty_ids and students_ids can exist in the LogIn table, but only a single or unique
faculty_id can be in the Faculty table and a unique student_id in the Student table. In
other words, the LogIn class is in the many (child) side of a one - to - many relationship.
Therefore, generally, the member variable of this kind of entity class is named LogIn s ,
and an “ s ” is attached to the name of the related entity class.
D. The foreach loop is utilized to pick up each column from the selected data row log, which
is obtained from the loginfo we get from the LINQ query. Then, assign two columns, log.
user_name and log.pass_word, to our two local string variables, username and password.
private void cmdLogIn_Click(object sender, EventArgs e)
{
string username = string.Empty;
string password = string.Empty;
SelectionForm selForm = new SelectionForm();
IQueryable<LogIn> loginfo = from lg in cse_dept.LogIns
where lg.user_name == txtUserName.Text &&
lg.pass_word == txtPassWord.Text
select lg;
foreach (LogIn log in loginfo)
{
username = (string)log.user_name;
password = (string)log.pass_word;
}
if (txtUserName.Text == string.Empty || txtPassWord.Text == string.Empty)
MessageBox.Show("Enter a valid username/password");
else if (username == txtUserName.Text && password == txtPassWord.Text)
{
MessageBox.Show("The LogIn is successful!");
selForm.Show();
this.Hide();
}

else
MessageBox.Show("The LogIn is failed!");
}
A
B
C
D
E
F
G
S
QLSelectRTObjectLINQ.LogInForm cmdLogIn_Click()

Figure 5.145
Codes for the LogIn button Click method.
c05.indd 390c05.indd 390 2/11/2010 2:59:05 PM2/11/2010 2:59:05 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

5.19 Query Data Using Runtime Objects to SQL Server Database

391
The purpose of this assignment operation is to avoid the possible overhead cycles when
identifying the validity of the username and password entered by the user. In other words,
we prefer to do this validation outside of this foreach loop. You can try to do it inside this
loop but defi nitely you would encounter some bugs. Since we are using a typed data table
and database, we can directly access each column by using its name without using the
fi eld < string > and the column ’ s name as the position for each of them.
E. An error message will be displayed if any of input box is empty to remind user to enter
valid username and password.
F. If both username and password are correct and matched to both columns queried from

the LogIn table, a successful message is displayed and our next form, SelectionForm, is
displayed and the current form is removed from the screen. The point is that this successful
message is only for the testing purpose and it should be commented out during the normal
running process of this project.
G. If no matched username and password can be found, an error message is displayed to
indicate this situation.
It looks like this query is quite simple, and all columns in the LogIn table have been
in there even if we did not explicitly perform any query to that table. The reason behind
this simple query is that no login information is actually retrieved until all columns in the
LogIn class are referenced, and this is called deferred loading. This terminology is used
to describe the type of loading in which columns are not actually loaded from the database
until they are required or referenced.
The code for the Cancel button Click method is easy and it is shown in Figure 5.146 .
The coding for the user - defi ned method getLogInForm() is also shown in this fi gure. This
is all the coding developments for the LogIn form. Before we can test this coding, we
prefer to fi nish the coding for the next form, SelectionForm.
5.19.3.3 Coding for Selection Form
The coding for this form is basically identical with the same form we did for the last
SQLSelectRTObject project, and the only difference is that the database connection
object we used in this project is an instance of the derived class CSE_DEPTDataContext.
Another point is that we do not need to add the namespace System.Data.Linq to the
namespace declaration section in this form since the LINQ to SQL will not be used for
this form.
private void cmdCancel_Click(object sender, EventArgs e)
{
cse_dept.Connection.Close();
Application.Exit();
}
public LogInForm getLogInForm()
{

return this;
}
A
B
SQLSelectRTObjectLINQ.LogInForm cmdCancel_Click()

Figure 5.146
Codes for the Cancel button Click method.
c05.indd 391c05.indd 391 2/11/2010 2:59:05 PM2/11/2010 2:59:05 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
392

Chapter 5 Data Selection Query with Visual C#.NET
Open the SelectionForm and enter the codes shown in Figure 5.147 into the code
window of this form. Most of code is identical with the same form we did for the
SQLSelectRTObject project except for the following codes:
A. When we click on the Exit button, fi rst we need to check whether our connection object
is still active or open. If it is open, we need to close this connection before we can exit the
project. Otherwise a bug would be created in this project if you exit the project without
closing the database connection.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SQLSelectRTObjectLINQ
{

public partial class SelectionForm : Form
{
FacultyForm facultyForm = new FacultyForm();
CourseForm courseForm = new CourseForm();
StudentForm studentForm = new StudentForm();
public SelectionForm()
{
InitializeComponent();
this.ComboSelection.Items.Add("Faculty Information");
this.ComboSelection.Items.Add("Course Information");
this.ComboSelection.Items.Add("Student Information");
this.ComboSelection.SelectedIndex = 0;
}
private void cmdOK_Click(object sender, EventArgs e)
{
if (this.ComboSelection.Text == "Faculty Information")
facultyForm.Show();
else if (this.ComboSelection.Text == "Course Information")
courseForm.Show();
else
if (this.ComboSelection.Text == "Student Information")
studentForm.Show();
else
MessageBox.Show("Invalid Selection!");
}
private void cmdExit_Click(object sender, EventArgs e)
{
LogInForm logForm = new LogInForm();

logForm = logForm.getLogInForm();

if (logForm.cse_dept.Connection.State == ConnectionState.Open)
logForm.cse_dept.Connection.Close();
logForm.Close();
courseForm.Close();
facultyForm.Close();
studentForm.Close();
Application.Exit();
}
}
}
A
B
SQLSelectRTObjectLINQ.SelectionForm SelectionForm()

Figure 5.147
Codes for the SelectionForm.
c05.indd 392c05.indd 392 2/11/2010 2:59:05 PM2/11/2010 2:59:05 PM
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

×