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"

 

Xây dựng Menu đa cấp với Multi Sitemap

Để tránh việc trình duyệt phải quay lại server và lấy dữ liệu từ database quá nhiều chúng ta có thể xây dựng menu đa cấp bằng cách dùng asp:Menu  sử dụng Site Map file. Bạn hãy xây dựng cho mình 1 control để sử dụng được nhiều Site map trong website của bạn. Mình sẽ hướng dẫn các bạn xây dựng để có thể sử dụng Menu đa cấp với MultiSitemap
1. Xây dựng Control menu
Bạn hãy tạo một thư mục Controls (Bạn có thể không cần tạo thư mục nhưng theo mình thì bạn nên tạo vì trong dự án của mình có thể có nhiều controls) sau đó nhấn phải chuột vào thư mục này, Chon Add New Item… tiếp theo chọn Web User Control đặt tên cho Control của bạn (ucMenuMultiSitemap.ascx)

Nội dung trong file Control (ucMenuMultiSitemap.ascx) như sau:

<asp:Menu 
    id="mnMainMeNu" 
    runat="server" 
    StaticEnableDefaultPopOutImage="False" 
    Orientation="Horizontal" 
    Height="20px"
    EnableTheming="True"
    DynamicVerticalOffset="0" 
    DynamicHorizontalOffset="0">
    <StaticMenuStyle 
        BorderStyle="Outset" 
        BorderWidth="0px" 
        CssClass="IE8Fix" 
        Height="23px"  />
    <StaticMenuItemStyle 
        CssClass="IE8Fix" 
        ForeColor="Black" 
        Height="20px"
        HorizontalPadding="7px"  />
    <DynamicMenuStyle 
        BorderStyle="Outset" 
        BorderWidth="1px" 
        CssClass="IE8Fix"  />
    <DynamicMenuItemStyle 
        CssClass="IE8Fix" 
        ForeColor="Black"
        Height="21px" 
        HorizontalPadding="7px" 
        Width="150px"  />
    <DynamicHoverStyle 
        BackColor="SteelBlue" 
        CssClass="IE8Fix" 
        ForeColor="White" 
        Height="20px"  />
    <StaticHoverStyle 
        BackColor="SteelBlue" 
        CssClass="IE8Fix" 
        ForeColor="White"  />
    <DataBindings> 
        <asp:MenuItemBinding
            DataMember="siteMapNode" 
            TextField="title"  
            NavigateUrlField="url"  /> 
    </DataBindings>
</asp:Menu>

Trong file code C# (ucMenuMultiSitemap.ascx.cs) bạn viết như 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;

public partial class Controls_ucMenuMultiSitemap : System.Web.UI.UserControl
{
    /// <summary>
    /// Định nghĩa các loại menu
    /// </summary>
    public enum MenuSitemap
    {
        TopMenu, BottomMenu, NotSet, LeftMenu, RightMenu
    }
    MenuSitemap eMenuToLoad = MenuSitemap.NotSet;
    public MenuSitemap MenuToLoad
    {
        get { return eMenuToLoad; }
        set { eMenuToLoad = value; }
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        mnMainMeNu.DataSource = GetMenuDataSource(eMenuToLoad, Server.MapPath("~"));
        mnMainMeNu.DataBind();
    }
    /// <summary>
    /// Lấy menu theo tùy chọn menu và tên file sitemap
    /// </summary>
    XmlDataSource GetMenuDataSource(MenuSitemap menu, string serverMapPath)
    {
        XmlDataSource objData = new XmlDataSource();
        objData.XPath = "siteMap/siteMapNode";
        switch (menu)
        {
            case MenuSitemap.TopMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuTop.sitemap";
                break;
            case MenuSitemap.BottomMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuBottom.sitemap";
                break;
            case MenuSitemap.LeftMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuLeft.sitemap";
                break;
            case MenuSitemap.RightMenu:
                objData.DataFile = serverMapPath + @"\App_Data\MenuRight.sitemap";
                break;
            default:
                break;
        }
        objData.DataBind();
        return objData;
    }
}

Vậy là xong phần xây dựng Control menu

2. Sử dụng Control menu

Để sử dụng Control này trước tiên bạn cần khai báo như sau (Đặt trên thẻ <!DOCTYPE)

<%@ Register TagPrefix="hmwebmenu" TagName="MyMenu" Src="~/Controls/ucMenuMultiSitemap.ascx" %>

Sau đó trong nội dung nơi mà bạn muốn đặt menu của bạn, bạn chỉ cần sử dụng thẻ menu như sau:

<hmwebmenu:MyMenu ID="MyMenu1" runat="server" MenuToLoad="BottomMenu" />
<%--Trong thẻ trên bạn chọn MenuToload=”BottomMenu” là để menu của bạn đọc nội dung từ file MenuBottom.sitemap được khai báo trong hàm GetMenuDataSource, Nếu không muốn khai báo trong trang aspx, bạn có thể dùng codebehind để thực hiện --%>

Kết quả khi chạy như sau:

Bạn cần chú ý trong thẻ <style> bạn cần có IE8Fix để sử dụng trong menu nếu không với trình duyệt IE8 sẽ không chạy được với asp:menu.

<style>
.IE8Fix
{
    z-index: 1000;
}
</style>

Bạn có thể download source về và chạy thử. 

MultiSitemapMenu.rar (4,18 kb)

Bạn có thể thắc mắc khi lấy nội dung từ database để tạo menu đa cấp. Việc đó cũng không khó khăn. ở bài sau mình sẽ hướng dẫn cách bind dữ liệu từ database ra file.sitemap. Bạn xem hàm viết bằng SQL

Mở rộng bài này bạn có thể thực hiện việc phân quền cho ứng dụng. Ví dụ ứng dụng của bạn có 2 mức quyền là admin và User khi đó bạn cần tạo 2 file admin.sitemap và user.sitemap, còn việc phân quyền đề khi nào thì gọi các file tương ứng thì cũng không có gì khó khăn

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

Chuyển đổi xâu ký tự từ TCVN3 sang Unicode C#

Trong nhiều trường hợp cần phải chuyển đổi mã từ TCVN 3 sang Unicode. Bài này giới thiệu một thuật toán đơn giản cho phép chuyển đổi một xâu ký tự từ TCVN 3 sang Unicode.  Ý tưởng của thuật toán là xây dựng hai mảng chứa các ký tự tiếng Việt có dấu cho mã TCVN 3 và Unicode. Để không phải tìm kiếm mỗi khi gặp ký tự có dấu, cần xây dựng một mảng trung gian để chuyển đổi, điều này làm giảm đáng kể thời gian chuyển đổi.

using System;
using System.Collections.Generic;
using System.Text;

class Converter {
    private static char[] tcvnchars = {
        ‘µ’, ‘¸’, ‘¶’, ‘·’, ‘¹’, 
        ‘¨’, ‘»’, ‘¾’, ‘¼’, ‘½’, ‘Æ’, 
        ‘©’, ‘Ç’, ‘Ê’, ‘È’, ‘É’, ‘Ë’, 
        ‘®’, ‘Ì’, ‘Ð’, ‘Î’, ‘Ï’, ‘Ñ’, 
        ‘ª’, ‘Ò’, ‘Õ’, ‘Ó’, ‘Ô’, ‘Ö’, 
        ‘×’, ‘Ý’, ‘Ø’, ‘Ü’, ‘Þ’, 
        ‘ß’, ‘ã’, ‘á’, ‘â’, ‘ä’, 
        ‘«’, ‘å’, ‘è’, ‘æ’, ‘ç’, ‘é’, 
        ‘¬’, ‘ê’, ‘í’, ‘ë’, ‘ì’, ‘î’, 
        ‘ï’, ‘ó’, ‘ñ’, ‘ò’, ‘ô’, 
        ‘­’, ‘õ’, ‘ø’, ‘ö’, ‘÷’, ‘ù’, 
        ‘ú’, ‘ý’, ‘û’, ‘ü’, ‘þ’, 
        ‘¡’, ‘¢’, ‘§’, ‘£’, ‘¤’, ‘¥’, ‘¦’
    };

    private static char[] unichars = {
        ‘à’, ‘á’, ‘ả’, ‘ã’, ‘ạ’, 
        ‘ă’, ‘ằ’, ‘ắ’, ‘ẳ’, ‘ẵ’, ‘ặ’, 
        ‘â’, ‘ầ’, ‘ấ’, ‘ẩ’, ‘ẫ’, ‘ậ’, 
        ‘đ’, ‘è’, ‘é’, ‘ẻ’, ‘ẽ’, ‘ẹ’, 
        ‘ê’, ‘ề’, ‘ế’, ‘ể’, ‘ễ’, ‘ệ’, 
        ‘ì’, ‘í’, ‘ỉ’, ‘ĩ’, ‘ị’, 
        ‘ò’, ‘ó’, ‘ỏ’, ‘õ’, ‘ọ’, 
        ‘ô’, ‘ồ’, ‘ố’, ‘ổ’, ‘ỗ’, ‘ộ’, 
        ‘ơ’, ‘ờ’, ‘ớ’, ‘ở’, ‘ỡ’, ‘ợ’, 
        ‘ù’, ‘ú’, ‘ủ’, ‘ũ’, ‘ụ’, 
        ‘ư’, ‘ừ’, ‘ứ’, ‘ử’, ‘ữ’, ‘ự’, 
        ‘ỳ’, ‘ý’, ‘ỷ’, ‘ỹ’, ‘ỵ’, 
        ‘Ă’, ‘Â’, ‘Đ’, ‘Ê’, ‘Ô’, ‘Ơ’, ‘Ư’
    };

    private static char[] convertTable;

    static Converter() {
        convertTable = new char[256];
        for (int i = 0; i < 256; i++)
            convertTable[i] = (char)i;
        for (int i = 0; i < tcvnchars.Length; i++)
            convertTable[tcvnchars[i]] = unichars[i];
    }

    public static string TCVN3ToUnicode(string value) {
        char[] chars = value.ToCharArray();
        for (int i = 0; i < chars.Length; i++)
            if (chars[i] < (char)256)
                chars[i] = convertTable[chars[i]];
        return new string(chars);
    }
}

Convert String To Decimal

private decimal ToDecimal(string Value)
{
 if (Value.Length == 0)
                return 0;
        else
                return Decimal.Parse(Value.Replace(" ", ""), NumberStyles.AllowThousands 
   | NumberStyles.AllowDecimalPoint | NumberStyles.AllowCurrencySymbol);
}

String Format for Int [C#]

Integer numbers can be formatted in .NET in many ways. You can use static method String.Format or instance method int.ToString. Following examples shows how to align numbers (with spaces or zeroes), how to format negative numbers or how to do custom formatting like phone numbers.

Add zeroes before number

To add zeroes before a number, use colon separator „:“ and write as many zeroes as you want.

 

String.Format("{0:00000}", 15);          // "00015"
String.Format("{0:00000}", -15);         // "-00015"

 

Align number to the right or left

To align number to the right, use comma „,“ followed by a number of characters. This alignment option must be before the colon separator.

 

String.Format("{0,5}", 15);              // "   15"
String.Format("{0,-5}", 15);             // "15   "
String.Format("{0,5:000}", 15);          // "  015"
String.Format("{0,-5:000}", 15);         // "015  "

 

Different formatting for negative numbers and zero

You can have special format for negative numbers and zero. Use semicolon separator „;“ to separate formatting to two or three sections. The second section is format for negative numbers, the third section is for zero.

 

String.Format("{0:#;minus #}", 15);      // "15"
String.Format("{0:#;minus #}", -15);     // "minus 15"
String.Format("{0:#;minus #;zero}", 0);  // "zero"

 

Custom number formatting (e.g. phone number)

Numbers can be formatted also to any custom format, e.g. like phone numbers or serial numbers.

 

String.Format("{0:+### ### ### ###}", 447900123456); // "+447 900 123 456"
String.Format("{0:##-####-####}", 8958712551);       // "89-5871-2551"