Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 11 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
11
Dung lượng
40,14 KB
Nội dung
Thựcthimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
Ở bài viết này mình sẽ hướng dẫn các bạn cách tạo một mệnhlệnh (command) và thựcthi trên cơsởdữ
liệu (database).
Tạo một mệnhlệnh (CREATING A COMMAND)
Có rất nhiều cách ngoài cách sử dụng SqlCommand nhưng mình sẽ dùng cách này để làm ví dụ vì nó
được cung cấp tốt nhất trong việc liên kết vớicơsởdữliệu SQL.
Mở Visual C# chọn Console Application và dùng thử code sau để phân tích :
[code]
using System;
using System.Data;
using System.Data.SqlClient;
class MenhLenh
{
public static void Main()
{
// tạo một kết nối
SqlConnection conn = new SqlConnection(@"Server = .\SQLEXPRESS;
Integrated Security = True;
Database = Northwind");
// tạo một đối tượng giữ lệnh cần thực thi
SqlCommand cmd = new SqlCommand();
Console.WriteLine("Command created.");
try
{
// mở kết nối
conn.Open();
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
finally
{
// đóng kết nối
conn.Close();
Console.WriteLine("Connection Closed.");
}
}
}
[/code]
Bài này chính xác là bài mình đã giới thiệu và dùng làm ví dụ trong bài trước ‘Tạo một kết nối tới cơsở
dữ liệu’ cho nên mình không nói thêm gì về phần đóng/mở kết nối tới hệ quản trị cơsởdữ liệu. Chỉ khác
ở chỗ có thêm 2 dòng code tạo thêm mệnhlệnh :
[code]
// tạo một đối tượng giữ lệnh cần thực thi
Page 1 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
SqlCommand cmd = new SqlCommand();
Console.WriteLine("Command created.");
[/code]
Ở đây thông qua lớp ‘SqlCommand’ mình tạo một đối tượng để nắm giữ thông tin về lệnh. Sau khi tạo
xong thì thông báo ra Console “Command created.” Chương trình về cơ bản là vậy rất đơn giản dễ hiểu.
Đó là cách tạo đối tượng nắm giữ mệnh lệnh. Mệnhlệnh tạo ra chỉ có tác dụng KHI VÀ CHỈ KHI nó
được chỉ định thựcthi trong kết nối nào. Vì vậy phải cho nó đi kèm với một kết nối tồn tại để tạo và thi
hành mệnhlệnh được viết ra.
Ví dụ sau mình sẽ minh họa các gán mệnhlệnh vào một kết nối.
[code]
using System;
using System.Data;
using System.Data.SqlClient;
class MenhLenh
{
public static void Main()
{
// tạo một kết nối
SqlConnection conn = new SqlConnection(@"Server = .\SQLEXPRESS;
Integrated Security = True;
Database = Northwind");
// tạo một đối tượng giữ lệnh cần thực thi
SqlCommand cmd = new SqlCommand();
Console.WriteLine("Command created.");
try
{
// mở kết nối
conn.Open();
// gán mệnhlệnh vào kết nối
cmd.Connection = conn;
Console.WriteLine("Connected command to connection !");
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
finally
{
// đóng kết nối
conn.Close();
Console.WriteLine("Connection Closed.");
}
}
}
[/code]
Page 2 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
Bạn dễ thấy ví dụ này cũng chính là ví dụ ban đầu nhưng mình chỉ có thay đổi thêm một chút trong khối
lệnh ‘try’
[code]
// gán mệnhlệnh vào kết nối
cmd.Connection = conn;
Console.WriteLine("Connected command to connection !");
[/code]
Sau khi ở trên mình đã tạo ra một kết nối tới cơsởdữliệu và một đối tượng nắm giữ mệnhlệnhthi hành
thì bên dướ mình thử gán mệnhlệnhvới kết nối.
Trong đối tượng của mệnhlệnhcó một thuộc tính (properties) để gán vào một kết nối nào đó :
CommandObject.Connection = ConnectionObject;
Như ở trên thì sau khi gán kết nối xong thì Console sẽ thông báo ra kết quả là gán mệnhlệnh vào kết nối
thành công.
Câu hỏi đặt ra ở đây là : Tại sao không gán kết nối ngay khi tạo ra đối tượng kết nối mà phải cho vào khối
‘try catch finally’ làm cái gì ?
Câu trả lời rất dễ hiểu: Bạn thử nghĩ xem sau khi bạn tạo kết nối thì muốn kích hoạt và kiểm tra kết nối
có tốt hay không thì phải ném vào trong khối ‘try catch’. Giả sử mà bạn khai báo gán mệnhlệnh ở ngay
trước khối ‘try catch’ và kết nối thành công thì không có lỗi gì cả. Nhưng trong trường hợp nếu có lỗi
biến cố bất ngờ xảy ra thì khi gán mệnhlệnh vào kết nối sẽ có lỗi và chương trình sẽ ngưng hoạt động và
ở tình trạng treo mà vẫn tiêu thụ tài nguyên máy, rất lãng phí. Vì vậy mà tốt nhất gán trong khối
‘try catch’ sau khi mở kết nối để gặp lỗi thì ta có thể biết được lỗi và nguyên nhân gây lỗi và sửa
(debug).Giải thích thế này không biết có hiểu không ^_^!
Tuy nhiên nếu bạn chắc chắn là kết nối đảm bảo tốt thì bạn có thể gán mệnhlệnh vào kết nối ngay từ đầu
và rút ngắn lại code
[code]
SqlCommand cmd = conn.CreateCommand();
[/code]
Tương đương với 2 dòng code
[code]
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
[/code]
Page 3 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
Bạn đã tạo được đối tượng nắm giữ mệnhlệnh và gán được vào kết nối, bây giờ phải viết mệnhlệnh cho
đối tượng.
Ta dùng thuộc tình ‘CommandObject.CommandText’ để tạo một lệnh cần thựcthivớicơsởdữ liệu.
Bạn vẫn dùng code ở trên nhưng chỉ thay đổi đi phần code trong khối ‘try catch’ bằng phần code dưới
đây nhé :
[code]
try
{
// mở kết nối
conn.Open();
// gán mệnhlệnh vào kết nối
cmd.Connection = conn;
Console.WriteLine("Connected command to connection !");
// tạo một lệnh cho đối tượng
cmd.CommandText = @" SELECT count(*) FROM Employees ";
Console.WriteLine(" Ready to execute SQL command : {0} ",
cmd.CommandText);
}
[/code]
Bạn để ý ở đây tớ có thêm 2 dòng code khác bên dưới.
‘CommandText’ ở đây là một lệnh SQL, nếu bạn viết cái gì đó khác hơn là một câu lệnh SQL thì sẽ có lỗi
thông báo khi thựcthilệnh này, đây là đoạn trick nếu mà bạn không thông thạo về cấu trúc câu lệnh
SQL . Xem bài 1 ‘Cơ bản về SQL cho người mới bắt đầu’ để biết chút cơ bản ban đầu về SQL nhé.
Thực thimệnhlệnh (EXECUTING COMMAND)
Bây giờ thử thựcthi câu lệnh nhé xem kết quả thế nào. Nhưng khi thựcthi một lệnhthì kết quả sẽ cho ra
khác nhau nếu như bạn sử dụng phương thứcthựcthi (execution method) khác nhau. Có 4 cách thựcthi
lệnh theo bảng sau :
Phương thức (Method) Giá trị trả về (Return Value)
ExecuteNonQuey() Không trả về gì vì không phải query
ExecuteScalar() Một giá trị duy nhất
ExecuteReader() Không hoặc nhiều hàng
ExecuteXmlReader XML
À bạn có thể hiểu query là một biểu thứccó giá trị trả về.
Bây giờ vẫn bài ở trên tớ dùng ‘ExecuteScalar’ để thu giá trị lấy về
Page 4 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
[code]
using System;
using System.Data;
using System.Data.SqlClient;
class MenhLenh
{
public static void Main()
{
// tạo một kết nối
SqlConnection conn = new SqlConnection(@"Server = .\SQLEXPRESS;
Integrated Security = True;
Database = Northwind");
// tạo một đối tượng giữ lệnh cần thực thi
SqlCommand cmd = new SqlCommand();
Console.WriteLine("Command created.");
try
{
// mở kết nối
conn.Open();
// gán mệnhlệnh vào kết nối
cmd.Connection = conn;
Console.WriteLine("Connected command to connection !");
// tạo một lệnh cho đối tượng
cmd.CommandText = @"SELECT count(*) FROM Employees ";
Console.WriteLine("Ready to execute SQL command : {0} ",
cmd.CommandText);
// Thựcthi câu lệnh
Console.WriteLine("Number of Employees is {0} ",
cmd.ExecuteScalar());
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
finally
{
// đóng kết nối
conn.Close();
Console.WriteLine("Connection Closed.");
}
}
}
[/code]
Ở đây bạn sẽ thu kết quả là : ‘Number of Employees is 9’.
Bạn học thêm một câu lệnh SQL mới luôn nhé. Để đếm số dòng (rows) trong một bảng ta dùng tham số
‘count(*)’
Cách gọi :
Page 5 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
[code]
SELECT count(*) FROM <table_name>
[/code]
Giá trị trả về là kiểu ‘Object’ và có một kết quả nên sử dụng ‘ExecuteScalar’.
Bạn nên chú ý ở đây : ‘ExecuteScalar’ trả về kiểu ‘Object’ và trong môi trường .NET Framework thìcơ
sở dữliệucó thể chứa bất cứ kiểu dữliệu nào. Khi đưa ra Console dùng ‘WriteLine’ thì tất cả các kiểu
đều bị convert sang kiểu kí tự in ra màn hình hết.
Bạn có thể chuyển giá trị thu được về một kiểu nào đó nhưng nếu convert không hợp lệ thì sẽ có
‘Runtime Error : Invaliad type cast’ hay gì đó đại loại như thế.
Mình giả sử bài ở trên mình muốn giá trị thu về kiểu ‘Int’ thì mình code như sau :
[code]
int count = (int)cmd.ExecuteScalar();
Console.WriteLine(“ Number of Employees is {0} “, count);
[/code]
Nếu như mình vẫn dùng thêm cái code convert ở ngay trên đây và thay đổi đi câu lệnhthựcthi
(commandText) thành :
[code]
cmd.CommandText = “SELECT firstname FROM employees WHERE lastname = ‘Davolio’
[/code]
Thì với ExecuteScalar() sẽ trả về kiểu Object có giá trị là “Nancy” thực chất là kiểu String (C#) nhưng mà
ở trên bạn lại cast nó sang kiểu ‘Int’ và màn hình sẽ thông báo lỗi như sau
Unhandled Exception : System.InvalidCastException: Specified cast is not valid.
Kiểu ‘String’ không thể bị convert sang kiểu ‘Int’.
Bây giờ chúng ta cùng thực hiện câu lệnh thu về nhiều kết quả xem. Tất nhiên là sử dụng :
ExecuteReader()
[code]
using System;
using System.Data;
using System.Data.SqlClient;
class MenhLenh
Page 6 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
{
public static void Main()
{
// tạo một kết nối
SqlConnection conn = new SqlConnection(@"Server = .\SQLEXPRESS;
Integrated Security = True;
Database = Northwind");
// tạo một đối tượng giữ lệnh cần thực thi
SqlCommand cmd = new SqlCommand();
Console.WriteLine("Command created.");
try
{
// mở kết nối
conn.Open();
// gán mệnhlệnh vào kết nối
cmd.Connection = conn;
Console.WriteLine("Connected command to connection !");
// tạo một lệnh cho đối tượng
cmd.CommandText = @"SELECT firstname, lastname FROM Employees ";
Console.WriteLine("Ready to execute SQL command : {0} ",
cmd.CommandText);
// Thựcthi câu lệnh
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(" Employee name : {0} {1} ",
reader.GetValue(0), reader.GetValue(1));
}
reader.Close();
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
finally
{
// đóng kết nối
conn.Close();
Console.WriteLine("Connection Closed.");
}
}
}
[/code]
Ở đây ta dùng query đẻ lấy về họ tên trong bảng Employees.
Và phương thức : ExecuteReader() trả về giá trị là một đối tượng SqlDataReader. Vì thế ở đây tớ tạo ra
một đối tượng SqlDataReader là reader để thu nhận tất cả kết quả lấy dược từ database. Kết quả sẽ theo
từng dòng (row) và mỗi lần đọc ‘reader.Read()’ thì nó chứa giá trị có được từ bảng theo dòng và chi nắm
giữ thông tin lấy chứ không phải tất cả các cột có trong bảng. Ví dụ ở đây tớ chỉ lấy 2 cột họ và tên thì
mỗi hàng trong reader khi Read() thì chỉ có 2 value tương ứng với Value(1) là họ và Value(0) là tên. Nếu
Page 7 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
như ở đây mà bạn GetValue(i) với i khác 0 và 1 thì chương trình sẽ treo . Phương thức Read() sau mỗi lần
thực hiện thì nó sẽ trả về hàng tiếp theo. Do dó để đọc hết kết quả thu được ở đây tớ dùng vòng lặp
‘while’ đọc cho đến khi không còn hàng nào nữa thì thôi.
Để thựcthi một biểu thứcthì ta sử dụng : ExecuteNonQuery(). Đơn giản vì biểu thức chẳng trả về giá trị
gì cả. Ví dụ bên dưới minh họa cách dùng :
[code]
using System;
using System.Data;
using System.Data.SqlClient;
public class ThiHanhMenhLenh
{
public static void Main()
{
SqlConnection conn = new SqlConnection(@"Server = .\SQLEXPRESS;
Integrated Security = True;
Database = Northwind");
string querySelect = @"SELECT count(*) FROM Employees";
string queryInsert = @"INSERT INTO Employees (firstname,lastname)
VALUES ('Pete','Houston')";
string queryDelete = @"DELETE FROM Employees WHERE firstname = 'Pete'
AND lastname = 'Houston'";
SqlCommand cmdSelect = new SqlCommand(querySelect, conn);
SqlCommand cmdInsert = new SqlCommand(queryInsert, conn);
SqlCommand cmdDelete = new SqlCommand(queryDelete, conn);
try
{
conn.Open();
Console.WriteLine("Open connection !");
Console.WriteLine("Before INSERT : ");
Console.WriteLine(" Number of employees : {0} ",
cmdSelect.ExecuteScalar());
cmdInsert.ExecuteNonQuery();
Console.WriteLine("Insert complete !");
Console.WriteLine("After INSERT : ");
Console.WriteLine(" Number of employees : {0} ",
cmdSelect.ExecuteScalar());
cmdDelete.ExecuteNonQuery();
Console.WriteLine("Delete complete !");
Console.WriteLine("After DELETE : ");
Console.WriteLine(" Number of employees : {0} ",
cmdSelect.ExecuteScalar());
}
catch (SqlException sqle)
{
Page 8 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
Console.WriteLine(sqle.ToString());
}
finally
{
conn.Close();
Console.WriteLine("Close connection !");
}
}
}
[/code]
Như bạn thấy ở đây mình tạo ra hai đối tượng cmdInsert và cmdDelete dùng để thựcthi hai biểu thứcthi
hành xóa và chèn thêm giá trị vào bảng, vì thế mà nó không có giá trị trả về và dùng ExecuteNonQuery.
Việc thựcthimệnhlệnh không có gì khó khăn cả và phụ thuộc vào mục đích sử dụng của bạn để thu về
kết quả cần tìm.
Tham số truyền vào lệnh (COMMAND PARAMETERS)
Nhiều lúc mà code như trên ấy, mình muốn thay đổi mệnhlệnh chẳng lẽ cứ phải thay đổi cái
CommandText….Nếu như thế là code không linh đông, mình muốn thay đổi và thựcthi câu lệnh bất cứ
khi nào muốn thì lám sao. May thay .NET Framework có hỗ trợ tham số truyên vào lệnh trong biểu thức
SQL và ta có thể thay đổi thông tin cần thiết trong CommandText.
Nếu thủ công lao động chân tay thìcó thể theo kiểu này :
[code]
String fname = “Pete”;
String lname = “Houston”;
String value = “(‘” + fname + “’,” + “’” + lname + “’)”;
String queryInsert = @” INSERT INTO Employees (firstname, lastname) VALUES ” + value;
[/code]
Nhưng mà kiểu này thì khác gì làm như trên, nhìn code lại hoa cả mắt.
Cách tốt nhất là làm việc với tham số truyền trong SQL. Trong câu lệnh SQL thì tham số được kí hiệu với
dấu @ ở trước Ví dụvới câu lệnh INSERT :
[code]
INSERT INTO MyTable VALUES (@MyName, @MyNumber)
[/code]
Page 9 of 11
Thực thimệnhlệnhvớicơsởdữliệu Author : Xcross87 2007
OK ! Thử làm xem nó ra sao. Dưới đây là code minh họa
[code]
using System;
using System.Data;
using System.Data.SqlClient;
public class ThiHanhMenhLenh
{
public static void Main()
{
SqlConnection conn = new SqlConnection(@"Server = .\SQLEXPRESS;
Integrated Security = True;
Database = Northwind");
string fname = "Pete";
string lname = "Houston";
string querySelect = @"SELECT firstname, lastname FROM Employees WHERE
EmployeeID > 9";
string queryInsert = @"INSERT INTO Employees (firstname,lastname)
VALUES (@fname,@lname)";
SqlCommand cmdSelect = new SqlCommand(querySelect, conn);
SqlCommand cmdInsert = new SqlCommand(queryInsert, conn);
cmdInsert.Parameters.Add("@fname", SqlDbType.NVarChar, 10);
cmdInsert.Parameters.Add("@lname", SqlDbType.NVarChar, 20);
try
{
conn.Open();
Console.WriteLine("Open connection !");
cmdInsert.Parameters["@fname"].Value = fname;
cmdInsert.Parameters["@lname"].Value = lname;
cmdInsert.ExecuteNonQuery();
SqlDataReader reader = cmdSelect.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(" New Employee : {0} {1} ",
reader.GetValue(0), reader.GetValue(1));
}
reader.Close();
}
catch (SqlException sqle)
{
Console.WriteLine(sqle.ToString());
}
finally
{
conn.Close();
Console.WriteLine("Close connection !");
}
}
}
Page 10 of 11
[...]... lần thực hiện xong một lệnhthì bạn phải truyền lại CommandText nếu không lệnh sẽ không có hiệu lực Nhưng như thế thì rất là bất tiện vì thế một phương thức được tạo ra để chúng ta thi hành một lệnh nhiều lần : CommandObject.Prepare() Nhưng nếu mà thay đổi CommandText thì phương thức prepare() sẽ lập tức mất ngay hiệu lực Kết thúc bài về Thực thimệnhlệnh với cơsởdữliệu Bài tiếp theo : ‘Đọc dữ liệu. . .Thực thimệnhlệnh với cơsởdữliệu Author : Xcross87 2007 [/code] Đầu tiên ta khai báo tham số truyền vào trong chuôi lệnh thực thi SQL : [code] cmdInsert.Parameters.Add("@fname", SqlDbType.NVarChar, 10); cmdInsert.Parameters.Add("@lname", SqlDbType.NVarChar, 20); [/code] Sau đó thì truyền vào giá trị cần thực hiện của tham số : [code] cmdInsert.Parameters["@fname"].Value... lần : CommandObject.Prepare() Nhưng nếu mà thay đổi CommandText thì phương thức prepare() sẽ lập tức mất ngay hiệu lực Kết thúc bài về Thực thimệnhlệnh với cơ sởdữliệu Bài tiếp theo : ‘Đọc dữliệuvới Data Readers’ Các bạn xem index mục lục để xem chi tiết các bài viết Page 11 of 11 . Thực thi mệnh lệnh với cơ sở dữ liệu Author : Xcross87 2007
Ở bài viết này mình sẽ hướng dẫn các bạn cách tạo một mệnh lệnh (command) và thực thi trên. cơ sở dữ liệu. Chỉ khác
ở chỗ có thêm 2 dòng code tạo thêm mệnh lệnh :
[code]
// tạo một đối tượng giữ lệnh cần thực thi
Page 1 of 11
Thực thi mệnh lệnh