SqlCommand

Các bài viết trong: Quan hệ C# và Database
Phần 1: Kết nối C# với Database
Phần 2: Sql Command
Phần 3: SqlDataReader & Dataset
Phần 4: Stored Procedure
Phần 5: Function và Trigger

Trong bài tiếp theo này sẽ giới thiệu về SqlCommand tầm quan trong và cách sử dụng SqlCommand

Có thể hiểu ngắn gọn là Lớp SqlCommand tạo một đối tượng để nắm giữ thông tin về mệnh lệnh. Nó phải đi kèm với một kết nối tồn tại để tạo và thi hành mệnh lệnh được viết ra. Xem ví dụ sau:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

public partial class Database : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Khai báo chuỗi kết nối
        string connectString = @"Server =.\SQL2005;Initial Catalog=BaiTap;User ID=sa;Password=******";
        // Khai báo câu truy vấn
        string sql = @"SELECT  count(*) FROM Customers";
        // Tạo một connection tới máy chủ
        SqlConnection conn = new SqlConnection(connectString);
        try
        {
            conn.Open();
            SqlCommand cmd = new SqlCommand(sql, conn);
            Label1.Text="Số bản ghi:= "+cmd.ExecuteScalar();

        }
        catch (SqlException ex)
        {
            Console.WriteLine("Error: " + ex);
        }
        finally
        {
            conn.Close();
        }
    }
}

Trong trang aspx bạn tạo một Label (<asp:Label ID="Label1" runat="server" />) để hiển thị kết quả. Khi chạy sẽ cho kết quả là: Số bản ghi:= 91 ( 91 là tổng số bản ghi trong bảng Customers)
Lưu ý:
- Một SqlCommand thông thường được khởi tạo như trên nó phải đi với một query và một connection, cụ thể ở đây là sql và conn. Nó nên đặt trong khối lệnh try vì nếu đặt ở ngoài khi kết nối không thành công thì chương trình ngưng hoạt động, ở tình trạng treo mà vẫn tiêu hao tài nguyên.
- Các cách thực thi của SqlCommand

Phương thức (Method) Giá trị trả về (Return Value)
ExecuteNonQuery() Trả về số hàng bị ảnh hưởng bởi câu lệnh SQL. Thường được sử dụng với các câu lệnh không trả về dữ liệu như Insert, delete, update,...
ExecuteScalar() Trả về hàng đầu tiên, cột đầu tiên của (một tập hợp) kết quả, các hàng/cột còn lại (nếu có) sẽ bị bỏ qua. Thường được sử dụng với các câu lệnh chỉ trả về 1 hàng, 1 cột kết quả (vd đếm số lượng nhân viên trong công ty).
ExecuteReader() Trả về đối tượng SqlDataReader - thường dùng cho việc đọc kết quả trả về của câu lệnh SQL là 1 tập hợp gồm nhiều hàng, nhiều cột - đối tượng này sẽ được giới thiệu kỹ hơn trong phần sau.
ExecuteXmlReader() Trả về đối tượng XmlReader - thường dùng để đọc kết quả trả về của câu lệnh SQL được lưu trữ ở dạng XML.

Trong ví dụ trên câu lệnh truy vấn chỉ trả về một giá trị nên ta sử dụng ExecuteScalar() Trường hợp câu truy vấn trả về nhiều giá trị (Dữ liệu dạng bảng) khi đó ta sẽ sử dụng ExecuteReader() xem ví dụ sau:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

public partial class Database : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string strHTML = "";
        strHTML+="<table border=\"0\" width=\"550\" cellspacing=\"1\" cellpadding=\"0\" bgcolor=\"#999966\" id=\"table2\">";
        strHTML+="  <tr>";
        strHTML += "        <td bgcolor=\"#CC3300\" align=\"center\"><font color=\"#FFFFFF\">CustomerID</font></td>";
        strHTML += "        <td bgcolor=\"#CC3300\" align=\"center\"><font color=\"#FFFFFF\">CompanyName</font></td>";
        strHTML += "        <td bgcolor=\"#CC3300\" align=\"center\"><font color=\"#FFFFFF\">ContactName</font></td>";
        strHTML += "        <td bgcolor=\"#CC3300\" align=\"center\"><font color=\"#FFFFFF\">Country</font></td>";
        strHTML+="  </tr>";
        // Khai báo chuỗi kết nối
        string connectString = @"Server =.\SQL2005;Initial Catalog=Northwind;User ID=sa;Password=******";
        // Khai báo câu truy vấn
        string sql = @"SELECT TOP 10 CustomerID, CompanyName, ContactName, Country FROM Customers ";
        // Tạo một connection tới máy chủ
        SqlConnection conn = new SqlConnection(connectString);
        try
        {
            conn.Open();
            SqlCommand cmd = new SqlCommand(sql, conn);
            SqlDataReader reader = cmd.ExecuteReader();
            while (reader.Read())
            {
                strHTML += "    <tr>";
                strHTML += "        <td bgcolor=\"#FFFFFF\">" + reader.GetValue(0) + "</td>";
                strHTML += "        <td bgcolor=\"#FFFFFF\">" + reader.GetValue(1) + "</td>";
                strHTML += "        <td bgcolor=\"#FFFFFF\">" + reader.GetValue(2) + "</td>";
                strHTML += "        <td bgcolor=\"#FFFFFF\">" + reader.GetValue(3) + "</td>";
                strHTML += "    </tr>";
            }
            reader.Close();//Đóng SqlDataReader
        }

        catch (SqlException ex)
        {
            Console.WriteLine("Error: " + ex);
        }
        finally
        {
            conn.Close();
        }
        strHTML += "</table>";
        Literal1.Text = strHTML;
    }
}

 

Trong trang aspx bạn cần tạo <asp:Literal ID="Literal1" runat="server" /> để hiển thị dữ liệu
Kết quả hiển thị như minh họa sau:

 

protected void Page_Load(object sender, EventArgs e)
    {
        string connectString = @"Server =.\SQL2005;Initial Catalog=Northwind;User ID=sa;Password=******";
        string queryInsert = @"INSERT INTO Employees (firstname,lastname) VALUES ('Pete','Houston')";
        string queryDelete = @"DELETE FROM Employees WHERE firstname = 'Pete' AND lastname = 'Houston'";
        // Tạo một kết nối tới máy chủ
        SqlConnection conn = new SqlConnection(connectString);
        try
        {
            conn.Open();
            // Thực thi câu lệnh Insert
            SqlCommand cmdInsert = new SqlCommand(queryInsert, conn); 
            cmdInsert.ExecuteNonQuery();
            // Thực thi lệnh Delete
            SqlCommand cmdDelete = new SqlCommand(queryDelete, conn);
            cmdDelete.ExecuteNonQuery();

        }
        catch (SqlException ex)
        {
            Console.WriteLine("Error: " + ex);
        }
        finally
        {
            conn.Close();
        }
    }

 

 

Khi thực thi code như ví dụ trên nó sẽ lần lượt thêm và xóa một bản ghi trong bảng Employees bằng 2 lệnh
cmdInsert.ExecuteNonQuery();
cmdDelete.ExecuteNonQuery();
Tương tự như vậy bạn có thể viết câu lệnh cho việc update 1 bản ghi

Tiếp theo chúng ta sẽ tìm hiều về cách chuyền tham số cho PARAMETERS (khá quan trọng): Không lẽ mỗi lần thay đổi lệnh ta lại thay đổi các query? Từ bất cập mà parameters ra đời, nó cho phép ta truyền vào các tham số một cách linh động và hiệu quả. Bạn xem ví dụ sau để hiểu về  PARAMETERS:

 

string connectString = @"Server =.\SQL2005;Initial Catalog=Northwind;User ID=sa;Password=******";
        string queryInsert = @"INSERT INTO Employees (firstname,lastname) VALUES (@firstname,@lastname)";
        // Tạo một connection tới máy chủ
        SqlConnection conn = new SqlConnection(connectString);
        try
        {
            conn.Open();
            SqlCommand cmdInsert = new SqlCommand(queryInsert, conn);
            //Khởi tạo
            cmdInsert.Parameters.Add("@firstname", SqlDbType.NVarChar, 10);
            cmdInsert.Parameters.Add("@lastname ", SqlDbType.NVarChar, 20);
            //Truyền giá trị
            cmdInsert.Parameters["@firstname"].Value = "Bui ";
            cmdInsert.Parameters["@lastname "].Value = "Hung";
            //Thực thi lệnh
            cmdInsert.ExecuteNonQuery();
        }
        catch (SqlException ex)
        {
            Console.WriteLine("Error: " + ex);
        }
        finally
        {
            conn.Close();
        }

Như vậy là trong bảng Employees bạn đã có thêm 1 Employee với fristname = "Bui " và lastname ="Hung"

 

Kết nối C# với Database

Các bài viết trong: Quan hệ C# và Database
Phần 1: Kết nối C# với Database
Phần 2: Sql Command
Phần 3: SqlDataReader & Dataset
Phần 4: Stored Procedure
Phần 5: Function và Trigger

Việc hiểu quan hệ giữa C# và Database trong việc xây dựng các ứng dụng (website) là rất quan trọng, Trong loạt bài viết này sẽ cung cấp các kiến thức nền tảng trong việc kết nối C# với Database. Bạn xem và bổ xung kiến thức cho khả năng lập trình của mình.

Trong bài viết đầu tiên này mình sẽ giới thiệu về  Kết nối C# với Database

Microsoft cung cấp các "data provider" như sau:

Data Provider Namespace Connection Class
ODBC System.Data.Odbc OdbcConnection
OLE DB System.Data.Oledb OledbConnection
Oracle System.Data.OracleClient OracleConnection
SQL Server System.Data.SqlClient SqlConnection
SQL Server CESystem.Data.SqlServerCe SqlCeConnection

Trong đó thường sử dụng nhất là: ODBC, OLE DB, SQL Server. Trong đó SQL là được dùng rộng rãi nhất, vì vậy SQL sẽ được chọn để minh họa. Và mình sẽ sử dụng Northwind database là cơ sở dữ liệu mẫu có sẵn khi bạn cài SQL server.
Ta sẽ bắt đầu bằng việc mở kết nối như ví dụ dưới đây:

 

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

public partial class Database : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string connectString = @"Server =.\SQL2005;Initial Catalog=Northwind;User ID=sa;Password=******";
        // Tạo một connection tới máy chủ
        SqlConnection conn = new SqlConnection(connectionString);
        try
        {
            conn.Open();
            //thuc hien cac cong viec can thiet o day        
        }
        catch (SqlException ex)
        {
            Console.WriteLine("Error: " + ex);
        }
        finally
        {
            conn.Close();
        }
    }
}

Như vậy là xong việc kết nối.

 


Lưu ý:

  • Khối lệnh try..catch..finally là khối lệnh bạn nên luôn luôn thực hiện vì những lý do sau: Nếu bạn thực hiện lệnh conn.Open() thành công nó sẽ nhảy xuống thực hiện khối lệnh trong finally là conn.Close(), còn nếu kết nối không thành công nó sẽ xử lý ngoại lệ (Khối catch), sau đó cũng nhảy xuống thực hiện conn.Close(). Như vậy ta thấy dù kết nối thành công hay ko thành công thì việc conn.Close() trong khối lệnh finally đều được thực thi và nó sẽ hạn chế sự hao tổn tài nguyên. Vậy là cứ mở kết nối thực thi các yêu cầu xong ta lại đóng kết nối lại -> Sẽ không tốn tài nguyên.
  • Nếu bạn sử dụng  Windows Authentication thì chuỗi kết nối như sau: string connectString = @"Server =.\SQL2005;database=Northwind;Integrated Security = true";

Xử lý từ khóa tìm kiếm cho bài viết bằng SQL

Trong bài viết thương yêu cầu có tìm kiếm từ khóa và mình cần hiển thị cho người dùng biết các từ khóa có liên quan đến bài viết. Bài viết này mình sẽ giới thiệu một cách để thực hiện.

Tuy chưa thực sự tối ưu vì trong thuật toán có dùng con trỏ để tìm kiếm. Nếu có thời gian chịu khó phân tích lại thì sẽ tối ưu thuật toán hơn.

Ví dụ bạn có bài viết được mô tả như sau:

Bạn sẽ thấy bên dưới phần diễn giải của bài viết có các từ khóa liên quan.
Để làm được điều đó bạn cần tạo một bảng (TB_TuKhoa) để lưu trữ những từ khóa (Gọi nôm na là kho từ khóa).

 

CREATE TABLE [dbo].[TB_TuKhoa](
    [idKey] [int] IDENTITY(1,1) PRIMARY KEY  NOT NULL,
    [TuKhoa] [nvarchar](250) NOT NULL,
    [GhiChu] [nvarchar](250) NULL,
)

 Ví dụ dữ liệu của bạn như sau:

 

Giờ chúng ta sẽ viết thuật toán để lấy ra các từ khóa.

 Bạn viết 1 hảm để trả về kết quả là từ khóa của bài viết như sau

* Input NoiDung bài viết (Nvarchar)
* Output: Từ khóa liên quan

CREATE FUNCTION GetKeyword(
    @NoiDung nvarchar(4000)
)
RETURNS NVarChar(4000) 
AS
BEGIN
    DECLARE @KetQua nvarchar(4000) SET @KetQua='Từ khóa: '
    -- Khai báo 1 bảng tạm
    DECLARE @_Table TABLE  (Noidung nvarchar(4000) null)
    INSERT INTO @_Table(Noidung) VALUES (@NoiDung)
    DECLARE @Count int
    --Dùng con trỏ (vòng lặp) để tìm kiếm từ khóa
    DECLARE @TuKhoa Nvarchar(250) 
    DECLARE TuKhoa_Cursor CURSOR FOR 
    SELECT TuKhoa  FROM TB_TuKhoa order by newid()
    OPEN TuKhoa_Cursor 
    FETCH NEXT FROM TuKhoa_Cursor INTO @TuKhoa 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
    -- Nếu tìm thấy trong nội dung có từ khóa thì cộng thêm kết quả
     SELECT @Count =Count(*) FROM @_Table 
        WHERE Noidung LIKE N'%'+@TuKhoa+'%'
     IF @Count>0
        BEGIN
            SET @KetQua=@KetQua+@TuKhoa+', '
        END
    FETCH NEXT FROM TuKhoa_Cursor INTO @TuKhoa 
    END
    CLOSE TuKhoa_Cursor
    DEALLOCATE TuKhoa_Cursor

RETURN @KetQua
END
 Để sử dụng hàm trên và tránh việc mỗi lần view bài viết bạn lại yêu cầu thực hiện hàm đó thì  trong bảng bài viết (TB_BaiViet) của bạn tạo thêm trường Từ khóa
Dữ liệu trường này = dbo.GetKeyword(NoiDung)
 
Ví dụ:
SELECT dbo.GetKeyword(N'Bài viết này giới thiệu một số thủ thuật 
và lời khuyên liên quan đến những thắc mắc mà người dùng văn phòng 
thường gặp phải trong quá trình sử dụng Excel, Word.')
Sẽ cho kết quả là:  Từ khóa: WORD, Thủ thuật, EXCEL, lời khuyên, thắc mắc, người dùng , người dùng văn phòng , sử dụng Excel, 

Cách Insert và tạo bảng dữ liệu "động" trong SQL Server

Như chúng ta đã biết đối với các hệ thống Logging thì dữ liệu luôn được cập nhật hàng tháng, hàng ngày vì vậy đòi hỏi CSDL phải tương thích có nghĩa là Log trong tháng nào thì hệ thống sẽ Insert vào tháng đó tương ứng tráng việc Insert nhiều trong cùng 1 bảng dẫn đến việc Select chậm khi trả về kết quả.

Vì vậy đối với Log của mỗi tháng chúng ta sẽ tạo ra các bảng vd:

Tháng 1 năm 2010 hệ thống sẽ tự động tạo ra bảng tbl_Month_1_2010
Tháng 2 năm 2010 hệ thống sẽ tự động tạo ra bảng tbl_Month_2_2010
...
Tháng 12 năm 2010 hệ thống sẽ tự động tạo ra bảng tbl_Month_12_2010

Như vậy làm sao để hệ thống có thể tự tạo ra các bảng tương ứng với năm và tháng như vậy ?

Giải pháp của tôi là sử dụng SQL Job trong SQL Server, cái này bắt buộc bạn phải có Full quyền Administrator trên Server Database

Các bước như sau:

B1: Trong SQL Server bạn kéo xuống dưới có phần SQL Server Agent bạn phải Start nó lên nếu nó đang Stop

Bạn click chuột phải vào Jobs chọn New Job

B2: Tại đây bạn được yêu cầu nhập Name: Tên của Job ở đây tôi chọn là CreateTableLogging và owner là sa

B3: Sau khi ấn OK bạn chọn tiếp phần Steps và bạn chọn New Step, tại đây bạn được yêu cầu nhập Step Name tôi chọn là StepCreateTable và Type là Transact-SQL script (T-SQL) có nghĩa là chạy câu lệnh SQL.

Bạn chọn tiếp Database là tên Database bạn muốn thực thi
Phần Command bạn gõ câu lệnh sau để tạo bảng động

DECLARE @strCreateTable AS VARCHAR(1000)
SET @strCreateTable = 'CREATE TABLE tbl_Month_'
SET @strCreateTable += Cast(MONTH(GETDATE()) as varchar)
SET @strCreateTable += '_'
SET @strCreateTable += Cast(YEAR(GETDATE()) as varchar)
SET @strCreateTable +='('
SET @strCreateTable +='ID int PRIMARY KEY IDENTITY,'
SET @strCreateTable +='Name nvarchar(50)'
SET @strCreateTable +=')'
--PRINT(@strCreateTable)
EXEC(@strCreateTable)

Sau đó nhấn OK

B4: Tiếp đến bạn chọn phần Schedules (để đặt lịch chạy cho Job) ban chọn New Schedule ở đây bạn được yêu cầu nhập Schedule Name cho Job tôi chọn là ScheduleCreateTable, Phần tần suất (Frequency) tôi chọn Occurs chạy vào ngày 15 hàng tháng (Monthly) lúc 12h đêm.

B5: sau đó bạn ấn OK để hoàn tất việc đặt lịch chạy cho Job và OK để hoàn tất Job
và đây là kết quả

B6: Để chắc là Job của bạn có chạy đúng hay không thì bạn Click chuột phải vào Job vừa tạo chọn Start Job at Step...

B7: Nếu nó báo thế này thì có nghĩa là Job của bạn đã chạy chính xác

B8: Kiểm tra

Như vậy mới hoàn thành xong phần tạo bảng bước tiếp chúng ta phải insert vào bảng đó thế nào

DECLARE @strValue AS NVARCHAR(50)
DECLARE @strSQL AS VARCHAR(1000)
SET @strValue = 'Justin___'
SET @strValue += Cast(GETDATE() as varchar)

SET @strSQL = 'INSERT INTO tbl_Month_'
SET @strSQL += Cast(MONTH(GETDATE()) as varchar)
SET @strSQL += '_'
SET @strSQL += Cast(YEAR(GETDATE()) as varchar)
SET @strSQL += '([Name]) VALUES('''
SET @strSQL += @strValue
SET @strSQL += ''')'
--PRINT(@strSQL)
EXEC(@strSQL)

Trong bảng tbl_Month_xx_xxxx  này tôi có 2 trường là ID (tự tăng) và Name
sau đó tôi insert test các giá trị mà gán trong biến @strValue là "Justin___" + ngày hiện tại
sau khi insert xong dữ liệu của tôi sẽ là thế này

ID   Name
6    Justin___Dec 12 2009  9:25AM
7    Justin___Dec 12 2009  9:25AM
8    Justin___Dec 12 2009  9:25AM
9    Justin___Dec 12 2009  9:25AM

Kỹ thuật phân trang trong trang asp.net dùng Store

Trên website này có viết bài "Kỹ thuật phân trang bằng Store Procedure" nhưng nhiều bạn chưa áp dụng được nó để phân trang trong asp.net và có nhiều bạn hỏi cách làm. Bài này mình sẽ hướng dẫn các bạn sử dụng thuật toán của bài viết đó vào trang asp.net.

Trong bài viết "Kỹ thuật phân trang bằng Store Procedure" thì dữ liệu hiển thị sẽ được chia làm 2 phần, một phần là dữ liệu truy vấn, một phần là chuỗi html hiển thị phân trang. Vậy để sử dụng nó bạn cần đổ dữ liệu từ Store vào DataSet. Khi đó phần dữ liệu truy vấn sẽ là Table[0] và phần hiển thị phân trang là Table[1]. Vậy bạn cần viết hàm để thực hiện nó. Để thực hiện mình lấy database Northwind, truy vấn dữ liệu từ bảng Customrs. Với Stored Procedure spPhanTrangSQL bạn xem ở bài viết  "Kỹ thuật phân trang bằng Store Procedure"  còn Store truy vẫn dữ liệu mình viết như sau:

CREATE PROCEDURE [dbo].[spCustomers_PhanTrang]
@currPage int,
@recodperpage int,
@Pagesize int
AS
Begin
    Begin
    WITH s AS
    (
        SELECT ROW_NUMBER() 
            OVER(ORDER BY CustomerID, 
            CompanyName) AS RowNum, 
            CustomerID, 
            CompanyName, 
            ContactName, City 
        FROM Customers  
    )
    Select * From s 
    Where RowNum Between 
        (@currPage - 1)*@recodperpage+1 
            AND @currPage*@recodperpage
    END
    -- Tính tổng số bản ghi
    DECLARE @Tolal int
    SELECT @Tolal=Count(*) FROM Customers

    EXEC spPhanTrangSQL 
            @Tolal, 
            @currPage, 
            @Pagesize, 
            @recodperpage
END

Trong trang aspx bạn cần một Gridview và một Literal để hiển thị dữ liệu như sau:

<table cellpadding="0" cellspacing="0" width="620">
    <tr>
        <td style="width: 100%">
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" BackColor="White"
        BorderColor="#CC9966" BorderStyle="None" BorderWidth="1px" CellPadding="4" Width="620px">
        <RowStyle BackColor="White" ForeColor="#330099" />
        <Columns>
            <asp:BoundField DataField="RowNum" HeaderText="RowNum" SortExpression="RowNum" />
            <asp:BoundField DataField="CustomerID" HeaderText="CustomerID" SortExpression="CustomerID" />
            <asp:BoundField DataField="CompanyName" HeaderText="CompanyName" SortExpression="CompanyName" />
            <asp:BoundField DataField="ContactName" HeaderText="ContactName" SortExpression="ContactName" />
            <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
        </Columns>
        <FooterStyle BackColor="#FFFFCC" ForeColor="#330099" />
        <PagerStyle BackColor="#FFFFCC" ForeColor="#330099" HorizontalAlign="Center" />
        <SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="#663399" />
        <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="#FFFFCC" />
    </asp:GridView>
        </td>
    </tr>
    <tr>
        <td style="width: 100%">
            <asp:Literal ID="ltlPhanTrang" runat="server"/></td>
    </tr>
</table>

Khi chạy dữ liệu được hiển thị như hình minh họa sau:

 

Giờ chúng ta sẽ viết  Các hàm cần thực hiện hiển thị dữ liệu:
1. Hàm thực thi một Store đổ dữ liệu vào DataSet

private static DataSet ThucThiStore_DataSet(
        string StoredProcedure, 
        params SqlParameter[] Parameters)
    {
    //Khai báo cuỗi kết nối
        string ConnectionString = 
        @"Server =.\SQL2005;Initial Catalog=Northwind;User ID=sa;Password=sa"; 
        SqlConnection Conn = new SqlConnection(ConnectionString);
        SqlCommand Command = new SqlCommand(StoredProcedure, Conn);
        if (Parameters != null)
        {
            Command.Parameters.Clear();
            Command.Parameters.AddRange(Parameters);
        }
        DataSet ds = new DataSet(); SqlDataAdapter da = 
            new SqlDataAdapter(StoredProcedure, Conn);
        Command.CommandType = CommandType.StoredProcedure;
        da.SelectCommand = Command;
        try
        {
    //Mở kết nối
            Conn.Open();
            da.Fill(ds);
        }
        finally
        {
    // Đóng kết nối
            if (Conn.State == ConnectionState.Open)
                Conn.Close();
            Conn.Dispose();
        }
        return ds;
    }

2. Hàm lấy dữ liệu từ Store trả về một DataSet

private DataSet StoreToDataSet(
        int currPage, 
        int recodperpage, 
        int Pagesize)
    {
        DataSet dts = new DataSet();
        SqlParameter[] arrParam = {
                new SqlParameter("@currPage", SqlDbType.Int),
                new SqlParameter("@recodperpage", SqlDbType.Int),
                new SqlParameter("@Pagesize", SqlDbType.Int)
                };
        arrParam[0].Value = currPage;
        arrParam[1].Value = recodperpage;
        arrParam[2].Value = Pagesize;
        return ThucThiStore_DataSet("spCustomers_PhanTrang", arrParam);
    }

3. Hàm nạp dữ liệu để hiển thị

private void NapDuLieu(int currPage, int recodperpage, int Pagesize)
   {
       DataSet ds = StoreToDataSet(currPage, recodperpage, Pagesize);
       DataTable dtbData = ds.Tables[0];
       DataTable dtbPhanTrang = ds.Tables[1];
       if (dtbData.Rows.Count > 0)
       {
           GridView1.DataSource = dtbData;
           GridView1.DataBind();
           if (dtbPhanTrang.Rows.Count > 0)
           {
               ltlPhanTrang.Text = dtbPhanTrang.Rows[0]["PhanTrang"] + "";
           }
       }
   }

Trong hàm này bạn thấy dữ liệu được chia làm 2 phần như đã nói �� trên và Phân dữ liệu truy vấn là Table[0] được bind vào Gridview1 còn phần dữ liệu phân trang là Table[1] (Chỉ là 1 bản ghi dữ liệu dang html được gán vào ltlPhanTrang).
 
Trong hàm Page_Load bạn cần khai báo 1 biến page và hiển thị dữ liệu như sau:

protected void Page_Load(object sender, EventArgs e)
    {
        int page = int.Parse("0" + Request.QueryString["page"]);
    if (page == 0) page = 1;
        if (!IsPostBack)
        {
            NapDuLieu(page, 10, 5);
        }
    }

Xem hàm Page_Load bạn thấy mình truyền giá trị 10 là số bản ghi hiển thị cho mỗi trang (rowperpage) và giá trị 5 là số trang hiển thị mỗi phân đoạn (@PageSize)
 
Bạn có thể download mã nguồn trang asp mình viết về tham khảo tại đây.

PhanTrangaspx.rar (1,92 kb)

Tham khảo thêm bài viết về phân trang trong Gridview

Chúc bạn thành công