1/1/17

[ADO.NET] Lesson 01: Giới thiệu về ADO.NET

(The C# Station ADO.NET Tutorial) Lesson này sẽ giới thiệu các khái niệm chính của ADO.NET và các đối tượng mà bạn sẽ học trong các bài tiếp theo. Ngoài việc hiểu rõ hơn về khái niệm ADO.NET, bạn sẽ được biết thêm về các khái niệm cơ bản khác như data provider và các đối tượng connection, command, DataReader, DataSet, DataAdapter.


Giới thiệu


ADO.NET là một bộ các thư viện hướng đối tượng (OOP) cho phép bạn tương tác với dữ liệu nguồn. Thông thường thì dữ liệu nguồn là một cơ sở dữ liệu (database), nhưng nó cũng có thể là file text, exel hoặc XML. Theo những mục tiêu của hướng dẫn này, chúng ta sẽ chỉ xem xét tới cách ADO.NET làm việc với database.
Như bạn có thể biết rằng, có rất nhiều loại database hiện nay như Microsoft SQL Server, Microsoft Access, Oracle, Borland Interbase, và IBM DB2,… Để làm rõ hơn phạm vi của loạt bài này, tất cả ví dụ sẽ sử dụng SQL Server.

Data Provider

Chúng ta biết rằng ADO.NET cho phép tương tác với các loại dữ liệu và kiểu database. Mỗi loại dữ liệu cần một cách thức khác nhau để có thể truy xuất. Các loại dữ liệu cũ sử dụng giao thức ODBC, các loại dữ liệu mới hơn sử dụng giao thức OleDb. Vì vậy cần có một thư viện thống nhất để làm việc với chúng, đây chính là lý do mà ADO.NET được tạo ra.
ADO.NET cung cấp một cách thức chung để tương tác với nguồn dữ liệu, nhưng với mỗi loại dữ liệu bạn phải sử dụng một thư viện khác nhau. Các thư viện này được gọi là Data Provider và thường được đặt tên theo giao thức hoặc loại dữ liệu mà chúng cho phép bạn truy xuất. Table 1 liệt kê các data provider phổ biến, tiền tố (prefix) API mà chúng sử dụng và kiểu dữ liệu mà bạn có thể làm việc.

table 1.  ADO.NET Data Providers are class libraries that allow a common way to interact with specific data sources or protocols.  The library APIs have prefixes that indicate which provider they support.
Provider NameAPI prefixData Source Description
ODBC Data ProviderOdbcData Sources with an ODBC interface.  Normally older data bases.
OleDb Data ProviderOleDbData Sources that expose an OleDb interface, i.e. Access or Excel.
Oracle Data ProviderOracleFor Oracle Databases.
SQL Data ProviderSqlFor interacting with Microsoft SQL Server.
Borland Data ProviderBdpGeneric access to many databases such as Interbase, SQL Server, IBM DB2, and Oracle.

Một ví dụ có thể giúp bạn hiểu nghĩa của API prefix. Một trong những đối tượng ADO.NET bạn sẽ học là connection, chúng cho phép thiết lập một kết nối đến nguồn dữ liệu. Nếu bạn dùng OleDb Data Provider để kết nối, bạn sẽ cần dùng để đối tượng connection tên là OleDbConnection. Tương tự, đối tượng connection sẽ dùng prefix là Odbc hoặc Sql cho đối tượng OdbcConnection hoặc SqlConnection để kết nối với nguồn dữ liệu tương ứng. Như đã nói lúc đầu, ta sẽ học cách làm việc với SQL Server nên các đối tượng API của chúng ta sẽ có prefix là Sql.

Các đối tượng của ADO.NET

ADO.NET bao gồm nhiều đối tượng bạn có thể dùng với dữ liệu. Phần này giới thiệu một vài đối tượng chính bạn sẽ sử dụng. Theo tiến độ trong các bài viết sau, bạn sẽ khám phá thêm nhiều đối tượng ADO.NET và cách chúng được sử dụng trong mỗi lesson riêng. Các đối tượng dưới đây bắt buộc bạn phải biết để làm việc với dữ liệu khi dùng ADO.NET.

SqlConnection
Để tương tác với database, bạn phải có một kết nối tới nó. Kết nối giúp xác định database server, database name, user name, password, và các tham số cần thiết để kết nối tới database. Một đối tượng connection được dùng bởi đối tượng command vì thế chúng sẽ biết database nào để thực thi lệnh.

SqlCommand
Quá trình tương tác với database cần phải biết hành động nào bạn muốn xảy ra. Điều này được thực hiện bởi đối tượng command. Bạn dùng đối tượng command để gửi một câu lệnh SQL tới database. Một đối tượng command dùng một đối tượng connection để xác định database nào sẽ được truy xuất. Bạn có thể dùng một đối tượng command riêng lẻ để thực thi lệnh trực tiếp, hoặc để gắn một tham chiếu của đối tượng command cho một SqlDataAdapter – đối tượng giữ các command sẽ làm việc trên một nhóm dữ liệu như sẽ đề cập tới trong phần dưới.

SqlDataReader
Nhiều thao tác dữ liệu đòi hỏi bạn chỉ lấy một luồng dữ liệu để đọc. Đối tượng data reader cho phép bạn lấy được kết quả của một câu lệnh SELECT từ một đối tượng command. Để tăng hiệu suất, dữ liệu trả về từ một data reader là một luồng dữ liệu fast forward-only. Có nghĩa là bạn chỉ có thể lấy dữ liệu từ luồng theo một thứ tự nhất định. Mặc dù điều này có lợi về mặt tốc độ, nhưng nếu bạn cần phải thao tác dữ liệu, thì một DataSet sẽ là một đối tượng tốt hơn để làm việc.

DataSet
Đối tượng DataSet là một thể hiện của dữ liệu trong bộ nhớ. Chúng chứa nhiều đối tượng DataTable, bên trong DataTable lại có nhiều column và row, giống như các database table thông thường. Bạn thậm chí có thể định nghĩa dữ liệu giữa các table để tạo các quan hệ parent-child. DataSet được thiết kế đặc biệt để giúp quản lý dữ liệu trong bộ nhớ và để hỗ trợ các thao tác không cần kết nối (disconnected) trên dữ liệu. DataSet là một đối tượng được dùng bởi tất cả Data Provider, đó là lý do tại sao nó không có một Data Provider prefix trong tên gọi.

SqlDataAdapter
Đôi lúc dữ liệu mà bạn làm việc là read-only và bạn ít khi cần thay đổi dữ liệu nguồn. Vài trường hợp cần lưu trữ tạm dữ liệu trong bộ nhớ để hạn chế truy xuất đến database. Data adapter làm điều này dễ dàng bằng cách giúp bạn quản lý dữ liệu trong chế độ ngắt kết nối. Data adapter sẽ đổ vào DataSet khi đọc dữ liệu và thực hiện thay đổi dữ liệu một lượt vào database.
Data adapter chứa một tham chiếu đến đối tượng connection và mở/đóng kết nối tự động khi đọc và ghi dữ liệu vào database. Hơn nữa, data adapter chứa đối tượng command cho những thao tác SELECT, INSERT, UPDATE và DELETE trên dữ liệu. Bạn sẽ có một data adapter được định nghĩa cho mỗi table trong một DataSet và nó sẽ quản lý các giao tiếp với database cho bạn. Tất cả những gì bạn cần làm là chỉ cho data adapter khi nào nạp hoặc ghi vào database.

Tổng kết

ADO.NET là một kĩ thuật .NET để thao tác với nguồn dữ liệu. Bạn có một vài Data Provider, cho phép bạn giao tiếp với các nguồn dữ liệu khác nhau, dựa trên giao thức mà chúng dùng hoặc kiểu database. Không cần quan tâm đến điều này, với mỗi Data Provider được sử dụng, bạn sẽ dùng các đối tượng tương tự nhau để thao tác với dữ liệu. Đối tượng SqlConnection cho phép bạn quản lý một kết nối đến nguồn dữ liệu. SqlCommand cho phép bạn gửi lệnh đến dữ liệu. Để đọc dữ liệu nhanh theo cơ chế forward-only, sử dụng SqlDataReader. Nếu bạn muốn làm việc với dữ liệu đã ngắt kết nối, dùng một DataSet và hiện thực việc đọc và ghi đến dữ liệu nguồn bằng một SqlDataAdalter.
This is just the beginning – bài học đầu tiên trong các lesson về ADO Tutorial.

[ADO.NET] Lesson 02: Đối tượng SqlConnection

Lesson này sẽ mô tả về đối tượng SqlConnection và cách để kết nối tới database. Qua đó, bạn sẽ hiểu được các kiến thức về tạo, sử dụng và quản lý các đối tượng connection sao cho hiệu quả trong ADO.NET


Giới thiệu

Điều đầu tiên bạn cần là tạo một kết nối để xác định database nào cần làm việc. Nó sẽ quản lý tất cả các logic ở mức thấp kết hợp với các giao thức đặc trưng của database. Công việc mà bạn cần làm chỉ là tạo một đối tượng connection, mở kết nối và đóng kết nối sau khi đã hoàn thành công việc.
Mặc dù làm việc với connection rất đơn giản trong ADO.NET, bạn vẫn cần hiểu về connection để có một quyết định đúng khi viết mã lệnh truy xuất dữ liệu. Phải hiểu rằng mỗi kết nối là một tài nguyên quan trọng. Nếu bạn chỉ có một ứng dụng làm việc với database trong máy, bạn có thể không cần quan tâm đến nó. Tuy nhiên, với các ứng dụng doanh nghiệp, hàng trăm người dùng khắp công ty kết nối tới cùng một database. Mỗi kết nối  giống như một đường đây và số lượng của chúng nằm trong mức giới hạn. Trường hợp bạn có thể thấy rõ hơn là  một web site được truy cập với hàng trăm nghìn lượt mỗi ngày. Ứng dụng sẽ bắt và giữ các kết nối, điều này có thể gây ra những ảnh hưởng nghiêm trọng đến hiệu suất và vận hành của ứng dụng.
Mô hình sau cho ta thấy cách mà SqlConnection được sử dụng bởi các đối tượng ADO.NET khác:

Tạo một đối tượng SqlConnection

Một đối tượng SqlConnection giống như các đối tượng khác trong C#. Bạn chỉ cần khai báo một thể hiện của SqlConnection, như dưới đây:
SqlConnection conn = new SqlConnection(
“Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI”);
Đối tượng SqlConnection trên sử dụng constructor với một tham số kiểu string. Tham số này được gọi là chuỗi kết nối (connection string). Table 1 mô tả các phần của một connection string.
Table 1.  ADO.NET Connection String chứa các cặp key/value để xác định cách tạo một kết nối đến database.  Chúng bao gồm vị trí, tên của database và và chế độ bảo mật.
Connection String Parameter NameDescription
Data SourceIdentifies the server.  Could be local machine, machine domain name, or IP Address.
Initial CatalogDatabase name.
Integrated SecuritySet to SSPI to make connection with user’s Windows login
User IDName of user configured in SQL Server.
PasswordPassword matching SQL Server User ID.
Integrated Security sẽ bảo mật khi bạn làm việc trên một máy đơn. Tuy nhiên, bạn sẽ thường xuyên cần phải định rõ mức bảo mật dựa trên SQL Server User ID với quyền hạn được xác định cho ứng dụng bạn sử dụng. Đoạn mã sau sử dụng một connection string với tham số User ID và Password:
SqlConnection conn = new SqlConnection(
“Data Source=DatabaseServer;Initial Catalog=Northwind;User ID=YourUserID;Password=YourPassword”);
Lưu ý Data Source được gán cho DatabaseServer để chỉ ra rằng bạn có thể định danh một database trên một máy khác, thông qua mạng LAN, hoặc qua Internet. Ngoài ra, User ID và Password được thay thế cho tham số Integrated Security.

Sử dụng SqlConnection

Mục đích của việc tạo một đối tượng SqlConnection là để các mã lệnh ADO.NET khác có thể làm việc được với database. Các đối tượng ADO.NET khác, như SqlCommand và SqlDataAdapter dùng một connection như một tham số. Quá trình sử dụng SqlConnection gồm các bước sau:
  1. Tạo một SqlConnection.
  2. Mở connection.
  3. Truyền connection  cho các đối tượng ADO.NET khác.
  4. Thực hiện các thao tác database với các đối tượng ADO.NET này.
  5. Đóng connection.
Chúng ta đã thấy cách để tạo một đối tượng SqlConnection. Những bước còn lại, mở, truyền, sử dụng và đóng connection được thể hiện trong Listing 1.
Listing 1.  Using a SqlConnection
using System;
using System.Data;
using System.Data.SqlClient;

/// <summary>
/// Demonstrates how to work with SqlConnection objects
/// </summary>
class SqlConnectionDemo
{
    static void Main()
    {
        // 1. Instantiate the connection
        SqlConnection conn = new SqlConnection(
            "Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI");

        SqlDataReader rdr = null;

        try
        {
            // 2. Open the connection
            conn.Open();

            // 3. Pass the connection to a command object
            SqlCommand cmd = new SqlCommand("select * from Customers", conn);

            //
            // 4. Use the connection
            //

            // get query results
            rdr = cmd.ExecuteReader();

            // print the CustomerID of each record
            while (rdr.Read())
            {
                Console.WriteLine(rdr[0]);
            }
        }
        finally
        {
            // close the reader
            if (rdr != null)
            {
                rdr.Close();
            }

            // 5. Close the connection
            if (conn != null)
            {
                conn.Close();
            }
        }
    }
}
Như đã thấy trong Listing 1, bạn mở một connection bằng cách gọi phương thức Open của đối tượng SqlConnection, conn. Bất kì thao tác nào thực hiện với SqlCommand cũng sử dụng connection này.
Mã lệnh sử dụng connection là một SqlCommand – đối tượng thực hiện truy vấn đến bảng Customers trong database. Tập kết quả trả về dưới dạng một SqlDataReader và vòng lặp while đọc cột đầu tiên của mỗi dòng trong tập kết quả này, chính là cột CustomerID. Chúng ta sẽ thảo luận về đối tượng SqlCommand và SqlDataReader trong lesson sau. Hiện tại, điều quan trọng là bạn cần hiểu rằng các đối tượng sử dụng SqlConnection để biết được database nào sẽ được truy xuất.
Khi bạn sử dụng xong đối tượng connection, bạn phải đóng nó. Thực hiện thất bại có thể gây ra các hậu quả nghiêm trọng đến hiệu suất và khả năng của ứng dụng. Như bạn thấy trong Listing 1: phương thức Close() được gọi trong một khối finally và chúng ta đảm bảo rằng connection sẽ khác null trước khi đóng nó.
Lưu ý rằng chúng ta bao đoạn mã ADO.NET trong một khối try/finally. Khối finally giúp đảm bảo rằng một phần mã lệnh sẽ được thực thi, bất kể một ngoại lệ có xảy ra hay không. Bởi vì các connection là một tài nguyên hệ thống ít ỏi, bạn sẽ cần phải chắc chắn rằng chúng được đóng trong khổi finally.
Một điểm bạn nên làm khi đóng connection là đảm bảo connection khác null. Nếu có sai sót xảy ra khi tạo connection, nó sẽ là null và bạn không nên cố đóng một connection không hợp lệ, điều này sẽ gây ra một ngoại lệ.
Ví dụ này cho thấy cách để dùng đối tượng SqlConnection với SqlDataReader – đối tượng yêu cầu bạn phải thực hiện một lệnh đóng connection rõ ràng. Tuy nhiên, khi dùng mô hình dữ liệu ngắt kết nối, bạn không cần phải mở và đóng connection thủ công. Chúng ta sẽ xem xét về vấn đề này trong lesson sau khi tìm hiểu về đối tượng SqlDataAdapter.

Tổng kết

Các đối tượng SqlConnection cho phép các đối tượng ADO.NET khác biết database nào sẽ được truy xuất và cách để tạo một connection. Chúng được tạo bằng cách truyền một connection string với một danh sách các cặp key/value để định nghĩa connection. Các bước mà bạn quản lý một connection là tạo, mở, truyền (cho các đối tượng ADO.NET khác), sử dụng và đóng. Hãy đảm bảo đóng connection một cách chính xác khi bạn đã làm việc xong với nó để chắc chắn rằng bạn không có một sự rò rỉ tài nguyên kết nối.

[ADO.NET] Lesson 03: Đối tượng SqlCommand

Lesson này giới thiệu về đối tượng SqlCommand và cách sử dụng để thao tác với database. Qua bài viết này, bạn sẽ biết cách sử dụng các phương thức ExecuteReader(), ExecuteNonQuery() và ExecuteScalar() của đối tượng command.


Giới thiệu

Đối tượng SqlCommand cho phép bạn chọn kiểu tương tác mà bạn muốn thực hiện với database. Ví dụ, bạn có thể thực hiện các lệnh select, insert, modify, và delete các dòng trong một table của database. Đối tượng này có thể được dùng để hỗ trợ mô hình quản lý dữ liệu ngắt kết nối (disconnected), nhưng trong bài học này chúng ta chỉ dùng đối tượng SqlCommand làm việc độc lập. Bài học này cũng cho bạn thấy cách để lấy một giá trị đơn từ database, như là số dòng của một table.

Tạo một đối tượng SqlCommand

Tương tự như các đối tượng C# khác, bạn tạo đối tượng SqlCommand bằng cách khai báo một thể hiện của nó:
SqlCommand cmd = new SqlCommand(“select CategoryName from Categories”, conn);
Dòng trên là điển hình để tạo một đối tượng SqlCommand. Nó lấy một tham số là chuỗi lệnh bạn cần thực thi và một tham chiếu đến đối tượng SqlConnection. SqlCommand có một vài overload, mà bạn sẽ thấy trong các ví dụ của tutorial này.

Querying Data – Truy vấn dữ liệu

Khi dùng một lệnh SQL select, bạn lấy được một dữ liệu từ database để hiển thị. Để làm được điều này với SqlCommand, bạn cần dùng phương thức ExecuteReader() để trả về một đối tượng SqlDataReader. Chúng ta sẽ thảo luận về SqlDataReader trong bài tiếp theo. Ví dụ sau cho thấy cách dùng SqlCommand để lấy được một đối tượng SqlDataReader:
1// 1. Instantiate a new command with a query and connection
2SqlCommand cmd = new SqlCommand("select CategoryName from Categories", conn);
3
4// 2. Call Execute reader to get query results
5SqlDataReader rdr = cmd.ExecuteReader();
Trong ví dụ trên, chúng ta tạo một đối tượng SqlCommand, truyền chuỗi lệnh và đối tượng connection vào constructor. Sau đó chúng ta lấy về đối tượng SqlDataReader bằng cách gọi phương thức ExecuteReader() của đối tượng SqlCommand, cmd.

Inserting Data – Chèn dữ liệu

Để chèn dữ liệu vào database, dùng phương thức ExecuteNonQuery() của đối tượng SqlCommand. Đoạn code sau cho thấy cách chèn dữ liệu vào một bảng trong database:
01// prepare command string
02string insertString = @"
03    insert into Categories
04    (CategoryName, Description)
05    values ('Miscellaneous', 'Whatever doesn''t fit elsewhere')";
06
07// 1. Instantiate a new command with a query and connection
08SqlCommand cmd = new SqlCommand(insertString, conn);
09
10// 2. Call ExecuteNonQuery to send command
11cmd.ExecuteNonQuery();
Lưu ý hai dấu nháy đơn (‘’) trong chuỗi insertString của từ “doesn’’t” (không phải dấu nháy kép). Đây là cách để bạn chèn một dấu nháy đơn vào chuỗi trong trường hợp chuỗi đó được bao bởi hai dấu nháy đơn (‘) thay vì nháy kép (“). SQL sẽ xem hai dấu nháy đơn đứng sát nhau là một dấu nháy đơn, tương tự như cách viết (\’) trong C#.
Một điểm cần chú ý nữa là chúng ta xác định rõ các cột CategoryName và Description. Bảng Categories có một primary key là CategoryID. Chúng ta không cần chèn dữ liệu vào cột này bởi vì SQL Server sẽ tự động thêm vào. Nếu bạn thử thêm giá trị vào cột primary key, như CategoryID, một ngoại lệ sẽ được tạo ra.
Để thực thi lệnh này, chỉ cần đơn giản gọi phương thức ExecuteNonQuery() của đối tượng SqlCommand, cmd.

Updating Data – Cập nhật dữ liệu

Phương thức ExecuteNonQuery cũng được dùng để cập nhật dữ liệu, như đoạn mã sau:
01// prepare command string
02 string updateString = @"
03     update Categories
04     set CategoryName = 'Other'
05     where CategoryName = 'Miscellaneous'";
06
07 // 1. Instantiate a new command with command text only
08 SqlCommand cmd = new SqlCommand(updateString);
09
10 // 2. Set the Connection property
11 cmd.Connection = conn;
12
13 // 3. Call ExecuteNonQuery to send command
14 cmd.ExecuteNonQuery();
Một lần nữa, chúng ta đặt câu SQL trong một biến string, nhưng lần này chúng ta dùng một constructor khác của SqlCommand, chỉ có một tham số là câu lệnh SQL. Trong bước 2, chúng ta gán đối tượng SqlConnection, conn, cho property Connection của đối tượng SqlCommand, cmd.
Thay vì cách này, bạn có thể sử dụng constructor với hai tham số tương tự như cho đoạn mã insert phần trên. Nó cho thấy rằng bạn có thể thay đổi đối tượng connection gán cho một command bất kì lúc nào.
Bước cuối cùng, phương thức ExecuteNonQuery() thực thi lệnh update.

Deleting Data – Xóa dữ liệu

Bạn cũng có thể xóa dữ liệu bằng phương thức ExecuteNonQuery(). Ví dụ sau cho thấy cách xóa một dòng từ database với phương thức ExecuteNonQuery():
01// prepare command string
02 string deleteString = @"
03     delete from Categories
04     where CategoryName = 'Other'";
05
06 // 1. Instantiate a new command
07 SqlCommand cmd = new SqlCommand();
08
09 // 2. Set the CommandText property
10 cmd.CommandText = deleteString;
11
12 // 3. Set the Connection property
13 cmd.Connection = conn;
14
15 // 4. Call ExecuteNonQuery to send command
16 cmd.ExecuteNonQuery();
Ví dụ này sử dụng constructor không có tham số của SqlCommand. Thay vào đó, nó gán cho hai property CommandText và Connection của đối tượng SqlCommand, cmd.
Chúng ta cũng có thể dùng hai overload constructor trước đó của SqlCommand, dùng để insert và update, với kết quả tương tự. Điều này cho thấy rằng bạn có thể thay đôi cả chuỗi lệnh và đối tượng connection bất kì lúc nào.
Lời gọi phương thức ExecuteNonQuery()  gửi lệnh đến database.

Lấy một giá trị đơn

Đôi lúc tất cả những gì bạn cần từ database chỉ là một giá trị đơn, đó có thể là một giá trị đếm, tổng, trung bình, hoặc các giá trị kết hợp khác từ dữ liệu. Thực thi phương thức ExecuteReader() để lấy về một đối tượng SqlDataReader và tính toán kết quả trong mã lệnh của bạn không phải cách tốt để làm điều này. Cách tốt nhất là để database làm công việc này và trả về giá trị bạn cần. Ví dụ sau cho thấy cách làm điều này với phương thức ExecuteScalar():
1// 1. Instantiate a new command
2SqlCommand cmd = new SqlCommand("select count(*) from Categories", conn);
3
4// 2. Call ExecuteNonQuery to send command
5int count = (int)cmd.ExecuteScalar();
Câu truy vấn trong constructor của  SqlCommand sẽ lấy về giá trị đếm của tất cả dòng trong bảng Categories. Câu truy vấn này chỉ trả về một giá trị đơn. Phương thức ExecuteScalar() trong bước 2 trả về giá trị này. Bởi vì kiểu trả về của ExecuteScalar() là object, chúng ta cần ép kiểu để chuyển giá trị sang int.

Kết hợp tất cả với nhau

Để đơn giản, tôi cho thấy các đoạn mã ngắn trong những phần trước để minh họa các kĩ thuật tương ứng. Nó cũng rất hữu ích để xem cách mà mã lệnh thực hiện trong một đoạn mã hoàn chỉnh của chương trình. Listing 1 cho thấy tất cả mã lệnh được dùng trong ví dụ này, cùng với phương thức Main() để thực thi và hiển thị kết quả xuất ra:
Listing 1.  SqlConnection Demo
001using System;
002 using System.Data;
003 using System.Data.SqlClient;
004
005 ///
006<summary> /// Demonstrates how to work with SqlCommand objects
007 /// </summary>
008 class SqlCommandDemo
009 {
010     SqlConnection conn;
011
012     public SqlCommandDemo()
013     {
014         // Instantiate the connection
015         conn = new SqlConnection(
016            "Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI");
017     }
018
019     // call methods that demo SqlCommand capabilities
020     static void Main()
021     {
022         SqlCommandDemo scd = new SqlCommandDemo();
023
024         Console.WriteLine();
025         Console.WriteLine("Categories Before Insert");
026         Console.WriteLine("------------------------");
027
028         // use ExecuteReader method
029         scd.ReadData();
030
031         // use ExecuteNonQuery method for Insert
032         scd.Insertdata();
033         Console.WriteLine();
034         Console.WriteLine("Categories After Insert");
035         Console.WriteLine("------------------------------");
036
037        scd.ReadData();
038
039         // use ExecuteNonQuery method for Update
040         scd.UpdateData();
041
042         Console.WriteLine();
043         Console.WriteLine("Categories After Update");
044         Console.WriteLine("------------------------------");
045
046         scd.ReadData();
047
048         // use ExecuteNonQuery method for Delete
049         scd.DeleteData();
050
051         Console.WriteLine();
052         Console.WriteLine("Categories After Delete");
053         Console.WriteLine("------------------------------");
054
055         scd.ReadData();
056
057         // use ExecuteScalar method
058         int numberOfRecords = scd.GetNumberOfRecords();
059
060         Console.WriteLine();
061         Console.WriteLine("Number of Records: {0}", numberOfRecords);
062     }
063
064     ///
065<summary> /// use ExecuteReader method
066 /// </summary>
067     public void ReadData()
068     {
069        SqlDataReader rdr = null;
070
071         try
072         {
073             // Open the connection
074             conn.Open();
075
076             // 1. Instantiate a new command with a query and connection
077             SqlCommand cmd = new SqlCommand("select CategoryName from Categories", conn);
078
079             // 2. Call Execute reader to get query results
080             rdr = cmd.ExecuteReader();
081
082             // print the CategoryName of each record
083             while (rdr.Read())
084             {
085                 Console.WriteLine(rdr[0]);
086             }
087         }
088         finally
089         {
090             // close the reader
091             if (rdr != null)
092             {
093                 rdr.Close();
094             }
095
096             // Close the connection
097             if (conn != null)
098             {
099                 conn.Close();
100             }
101         }
102     }
103
104     ///
105<summary> /// use ExecuteNonQuery method for Insert
106 /// </summary>
107     public void Insertdata()
108     {
109         try
110         {
111             // Open the connection
112             conn.Open();
113
114             // prepare command string
115             string insertString = @"
116                 insert into Categories
117                 (CategoryName, Description)
118                 values ('Miscellaneous', 'Whatever doesn''t fit elsewhere')";
119
120             // 1. Instantiate a new command with a query and connection
121             SqlCommand cmd = new SqlCommand(insertString, conn);
122
123             // 2. Call ExecuteNonQuery to send command
124             cmd.ExecuteNonQuery();
125         }
126         finally
127         {
128             // Close the connection
129             if (conn != null)
130             {
131                 conn.Close();
132             }
133         }
134     }
135
136     ///
137<summary> /// use ExecuteNonQuery method for Update
138 /// </summary>
139     public void UpdateData()
140     {
141         try
142         {
143             // Open the connection
144             conn.Open();
145
146             // prepare command string
147             string updateString = @"
148                 update Categories
149                 set CategoryName = 'Other'
150                 where CategoryName = 'Miscellaneous'";
151
152             // 1. Instantiate a new command with command text only
153             SqlCommand cmd = new SqlCommand(updateString);
154
155             // 2. Set the Connection property
156             cmd.Connection = conn;
157
158             // 3. Call ExecuteNonQuery to send command
159             cmd.ExecuteNonQuery();
160        }
161         finally
162         {
163             // Close the connection
164             if (conn != null)
165             {
166                 conn.Close();
167             }
168         }
169     }
170
171     ///
172<summary> /// use ExecuteNonQuery method for Delete
173 /// </summary>
174     public void DeleteData()
175     {
176         try
177         {
178             // Open the connection
179             conn.Open();
180
181             // prepare command string
182             string deleteString = @"
183                 delete from Categories
184                 where CategoryName = 'Other'";
185
186             // 1. Instantiate a new command
187             SqlCommand cmd = new SqlCommand();
188
189             // 2. Set the CommandText property
190             cmd.CommandText = deleteString;
191
192             // 3. Set the Connection property
193             cmd.Connection = conn;
194
195             // 4. Call ExecuteNonQuery to send command
196             cmd.ExecuteNonQuery();
197         }
198         finally
199         {
200             // Close the connection
201             if (conn != null)
202             {
203                 conn.Close();
204             }
205         }
206     }
207
208     ///
209<summary> /// use ExecuteScalar method
210 /// </summary>
211     /// number of records
212     public int GetNumberOfRecords()
213     {
214         int count = -1;
215
216         try
217         {
218             // Open the connection
219             conn.Open();
220
221             // 1. Instantiate a new command
222             SqlCommand cmd = new SqlCommand("select count(*) from Categories", conn);
223
224             // 2. Call ExecuteScalar to send command
225             count = (int)cmd.ExecuteScalar();
226         }
227         finally
228         {
229            // Close the connection
230             if (conn != null)
231             {
232                 conn.Close();
233             }
234         }
235         return count;
236     }
237 }
Trong Lising 1, đối tượng SqlConnection được khởi tạo trong lớp SqlCommandDemo. Điều này hợp lệ vì đối tượng sẽ được dọn dẹp khi CLR garbage collector làm việc. Điều quan trọng là ta đóng connection sau khi sử dụng nó. Chương trình mở connection trong một khổi try và đóng nó trong một khối finally cho mỗi phương thức.
Phương thức ReadData() hiển thị nội dung của cột CategoryName của bảng Categories. Chúng ta dùng nó vài lần trong phương thức Main() để hiển thị trạng thái hiện tại của bảng Categories. Bảng này sẽ bị thay đổi khi mỗi lệnh insert, update, delete được thực hiện.

Tổng kết

Đối tượng SqlCommand cho phép bạn truy vấn và gửi lệnh đến một database. Nó có các phương thức sử dụng cho các lệnh khác nhau. Phương thức ExecuteReader() trả về một đối tượng SqlDataReader để hiển thị kết quả của câu truy vấn. Cho các lệnh insert, update và delete, bạn dùng phương thức ExecuteNonQuery(). Nếu bạn chỉ cần một giá trị đơn từ một câu truy vấn, phương thức ExecuteScalar() là lựa chọn tốt nhất.