Phần 4: Lập trình Cơ sở dữ liệu với C#


Lập trình Cơ sở dữ liệu là một phần rất quan trọng trong lập trình ứng dụng, nó là trung gian kết nối giữa người sử dụng với cơ sở dữ liệu.
Với công nghệ ADO.NET chúng ta có một chuẩn thống nhất để lập trình thao tác với các nguồn cơ sở dữ liệu khác nhau như Access, MySQL, SQL Server, Oracle… cũng như lập trình ứng dụng với dạng WinForm và WebForm.
Trong bài này chúng ta sẽ đi vào một bài tập cụ thể để tìm hiểu các đối tượng quan trọng trong ADO.NET để lập trình với CSDL như: Connection, Command, DataReader, DataAdapter, DataSet để kết nối đến hệ quản trị CSDL SQL Server.


Nội dung


Yêu cầu bài toán

Lập trình quản lý cơ sở dữ liệu QLBanHang có các bảng:

tblMatHang( MaSP nchar(5), TenSP nvarchar(30), NgaySX Date, NgayHH Date, DonVi nvarchar(10), DonGia float , GhiChu nvarchar(200))

tblNhaCC(MaNhaCC nchar(5), TenNhaCC nvarchar(50), DiaChi nvarchar(200), MaSoThue nvarchar(15), TaiKhoan nvarchar(15), DienThoai nvarchar(11))

tblHangNhap(MaSP nchar(5), MaNhaCC nchar(5), SoLuong int, DonGia float, SoHD nvarchar(10), NgayGH Date)

Hãy xây dựng giao diện và các chức năng Thêm mới, Sửa, Xoá, Tìm kiếm của các bảng trên tương tự như sau.
>Xem hướng dẫn tạo Database trong VisualStudio


Tổng quan Các đối tượng trong ADO.NET

1. Các .Net Data Provider trong ADO.Net

Sử dụng NameSpace System.Data để lập trình với ADO.NET
Các .Net Data Provider được sử dụng để kết nối tới cơ sở dữ liệu, thực thi các câu lệnh truy vấn (SQL) và lấy dữ liệu. Dữ liệu trả về có thể được xử lý trực tiếp, đặt trong đối tượng DataSet, được kết hợp với dữ liệu từ nhiều nguồn hoặc gửi dữ liệu giữa các tầng (tiers) trong mô hình lập trình nhiều tầng (N-Tier).
Trong .Net Framework có các .Net Data Provider mặc định sau:

  • .NET Data Provider cho SQL Server: sử dụng namespace System.Data.SqlClient
  • .NET Data Provider cho OLE DB: sử dụng namespace System.Data.OleDb
  • .NET Data Provider cho ODBC: sử dụng namespace System.Data.Odbc
  • .NET Data Provider cho Oracle: sử dụng namespace System.Data.OracleClient
  • EntityClient Provider: cung cấp truy cập dữ liệu cho các ứng dụng dạng Entity Data Model (EDM), sử dụng namespace System.Data.EntityClient
  • .NET Data Provider cho SQL Server Compact 4.0: cung cấp truy cập dữ liệu cho Microsoft SQL Server Compact 4.0, sử dụng namespace System.Data.SqlServerCe

2. Các đối tượng trong .Net Data Provider

  • Connection: thiết lập kết nối tới nguồn dữ liệu
  • Command: thực thi các câu lệnh truy vấn với nguồn dữ liệu từ một Connection
  • DataReader: cung cấp một luồng (stream) dữ liệu chỉ đọc từ nguồn dữ liệu
  • DataAdapter: đặt dữ liệu vào DataSet và cập nhật dữ liệu từ DataSet về nguồn dữ liệu

3. Các phương thức và thuộc tính quan trọng

a. Connection
  • Thuộc tính ConnectionString: truyền vào chuỗi kết nối tới nguồn dữ liệu
  • Phương thức Open: mở kết nối
  • Phương thức Close: đóng kết nối
b. Command
  • Thuộc tính CommandText: truyền vào câu lệnh SQL hoặc tên Stored procedure
  • Thuộc tính CommandType: kiểu câu lệnh SQL là StoredProcedure,
    TableDirect hay Text
  • Thuộc tính Connection: truyền vào đối tượng Connection
  • Phương thức ExecuteReader: thực thi với câu lệnh SQL Select và trả về luồng dữ liệu qua đối tượng DataReader
  • Phương thức ExecuteScalar: thực thi câu lệnh SQL Select và trả về một giá trị ở hàng đầu tiên và cột đầu tiên. Thích hợp với câu lệnh Select dạng thống kê như Count, Sum, AVG …
  • Phương thức ExecuteNonQuery: thực thi câu lệnh SQL như Insert, Update, Delete … và không trả về kết quả
  • Phương thức ExecuteXMLReader: thực thi câu lệnh truy vấn với các câu lệnh cho XML
c. DataReader
  • Phương thức Read: đọc các hàng dữ liệu
d. DataAdapter
  • Phương thức Fill: đổ dữ liệu từ nguồn dữ liệu vào DataSet
  • Phương thức Update: cập nhật dữ liệu từ DataSet tới nguồn dữ liệu
Cách thực thi đối tượng DataAdapter

Cách thực thi đối tượng DataAdapter


Thực hiện câu lệnh Select, hiển thị dữ liệu lên DataGrid

>>Xem hướng dẫn phần thiết kế giao diện

Để lập trình với CSDL, bạn cần biết các câu lệnh cơ bản để thao tác với CSDL như SELECT, INSERT, UPDATE, DELETE. Phần này chúng ta sẽ lập trình để hiển thị dữ liệu lên DataGridView

Cú pháp câu lệnh Select


SELECT danh_sách_các_cột FROM tên_bảng
WHERE danh_sách_các_điều_kiện

Các bước

Bước 1:Khai báo .Net Data Provider cho SQL Server


using System.Data.SqlClient;

Bước 2: Tạo đối tượng Connection, khởi gán chuỗi kết nối, mở kết nối


 //Tạo đối tượng Connection
 SqlConnection con = new SqlConnection();
 //Truyền vào chuỗi kết nối tới cơ sở dữ liệu
 //Sử dụng Application.StartupPath để lấy đường dẫn tới thư mục chứa file chạy chương trình 
 con.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=" + Application.StartupPath + @"\QLBanHang.mdf;Integrated Security=True;User Instance=True";
 con.Open(); // mở kết nối

Bước 3: Khai báo đối tượng DataAdapter để Fill dữ liệu vào DataSet


 //Lấy toàn bộ dữ liệu từ bảng tblMatHang
 String sql = "Select * from tblMatHang";
 //tạo đối tượng DataSet
 DataSet ds = new DataSet();
 //Khởi tạo đối tượng DataAdapter và cung cấp vào câu lệnh SQL và đối tượng Connection
 SqlDataAdapter dap = new SqlDataAdapter(sql,con);
 //Dùng phương thức Fill của DataAdapter để đổ dữ liệu từ DataSource tới DataSet
 dap.Fill(ds);

Bước 4: Gắn dữ liệu lên DataGrid


 //Gắn dữ liệu từ DataSet lên DataGridView
 dgvKetQua.DataSource = ds.Tables[0];
 dgvKetQua.Refresh();

>>Xem hướng dẫn phần hiển thị dữ liệu lên DataGridView


Thực hiện các câu lệnh Insert, Update, Delete dữ liệu

Cú pháp câu lệnh Insert


INSERT INTO tên_bảng(danh_sách_các_cột)
VALUES (danh_sách_các_giá_trị)

Các bước

Bước 1: Khởi tạo đối tượng Connection giống bước 2 phần trên
Bước 2: Khởi tạo đối tượng Command và thực thi câu lệnh Insert


 //Tạo câu lệnh truy vấn Insert lấy dữ liệu từ các Control trên Form thiết kế
 sql = "INSERT INTO tblMatHang(MaSP,TenSP,NgaySX,NgayHH,DonVi,DonGia,GhiChu)VALUES (";
 sql += "N'" + txtMaSP.Text + "',N'" + txtTenSP.Text + "','" + dtpNgaySX.Value.Date + "','" + dtpNgayHH.Value.Date + "',N'" + txtDonVi.Text + "',N'" + txtDonGia.Text + "',N'" + txtGhiChu.Text + "')";
//Thực thi câu lệnh SQL sử dụng đối tượng Command
 SqlCommand cmd = new SqlCommand(sql, con);
 cmd.ExecuteNonQuery();

Muốn lưu được dữ liệu tiếng việt cần thêm ký tự N đặt trước dữ liệu, giống như câu lệnh truy vấn ở trên

Cú pháp câu lệnh Update


UPDATE tên_bảng
SET 
    tên_cột_1 = giá_trị_1,
    tên_cột_2 = giá_trị_2,
    ...,
    tên_cột_n = giá_trị_n
[WHERE điều_kiện];

Các bước

thực hiện tương tự như phần trên, chỉ khác câu lệnh SQL Update.

Cú pháp câu lệnh Delete


DELETE FROM tên_bảng 
[WHERE điều_kiện]; 

Các bước

thực hiện tương tự như phần trên, chỉ khác câu lệnh SQL Delete.


Sử dụng các Stored Procedure

Thay vì viết câu lệnh SQL trực tiếp trong Code chương trình, chúng ta có thể khai thác các Stored Procedure để tái sử dụng và tăng hiệu năng sử dụng Stored Procedure. Xem thêm bài về Stored Procedure.

Các bước

Bước 1: Tạo Stored Procedure trong SQL Server, giả sử đặt tên là InsertMatHang


CREATE PROCEDURE InsertMatHang 
	@MaSP nachr(5),
	@TenSP nvarchar(30),
	@NgaySX Date,
        @NgaySX Date,
        @DonVi nvarchar(10),
        @DonGia float,
	@GhiChu nvarchar(200)
AS
   INSERT INTO tblMatHang(MaSP,TenSP,NgaySX,NgayHH,DonVi,DonGia,GhiChu)
   VALUES(@MaSP,@TenSP,@NgaySX,@NgayHH,@DonVi,@DonGia,@GhiChu) 

Bước 2: Viết code C# thực thi Stored Procedure


//B1. Tạo đối tượng Connection
SqlConnection con = new SqlConnection();
con.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=" + Application.StartupPath + @"\QLBanHang.mdf;Integrated Security=True;User Instance=True";
 con.Open(); // mở kết nối  
//B2. Tạo đối tượng Command
SqlCommand cmd = new SqlCommand();
//Thiết lập các thuộc tính cho đối tượng Command
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "InsertMatHang";
//B3. Gắn các Parameter và giá trị cho đối tượng Command
cmd.Parameters.Add(new SqlParameter("@MaSP", txtMaSP.Text));
cmd.Parameters.Add(new SqlParameter("@TenSP", txtTenSP.Text));
cmd.Parameters.Add(new SqlParameter("@NgaySX", dtpNgaySX.Value.Date));
cmd.Parameters.Add(new SqlParameter("@NgayHH", dtpNgayHH.Value.Date));
cmd.Parameters.Add(new SqlParameter("@DonVi", txtDonVi.Text));
cmd.Parameters.Add(new SqlParameter("@DonGia", txtDonGia.Text));
cmd.Parameters.Add(new SqlParameter("@GhiChu", txtGhiChu.Text));
//B4. Thực thi Stored Procedure
cmd.ExecuteNonQuery();


Lưu thông tin cấu hình trong file config

Như phần trên bạn thấy khi khởi tạo chuỗi kết nối cho đối tượng Connection chúng ta đang đặt code cứng (hard code), sẽ không mềm dẻo khi bạn đi triển khai ứng dụng cho khách hàng. Bạn có thể lưu trữ chuỗi kết nối trong file config của ứng dụng (file có tên app.config, một dạng file xml lưu trữ toàn bộ cấu hình ứng dụng). Khi đi triển khai ứng dung, chúng ta chỉ cần mở file app.config là có thể cấu hình cho ứng dụng mà không cần phải biên dịch lại code.

Các bước

Bước 1: vào Project > Chọn Project Properties > Settings > rồi đánh Name: QLMatHangConnectionString, Type: Connection string, Value: Chọn cấu hình tới CSDL của bạn
Bước 2: cập nhật trong Code:


SqlConnection objCon = new SqlConnection();
//Lấy dữ liệu chuỗi kết nối thông qua đối tượng Properties
objCon.ConnectionString = Properties.Settings.Default.QLMatHangConnectionString;

Download Sourcode


Tham khảo thêm

Có thể bạn sẽ thích…

32 phản hồi

  1. Sơn viết:

    Thầy hướng dẫn lại cho em chỗ thêm dữ liệu vào CSDL
    Hiện trên datagridview nhưng không lưu đc vào CSDL với ạ

    • Phan Tiến viết:

      Chào em,
      Em đang sử dụng chuỗi kết nối theo kiểu như thế này:
      con.ConnectionString = @”Data Source=.\SQLEXPRESS;AttachDbFilename=” + Application.StartupPath + @”\QLBanHang.mdf;Integrated Security=True;User Instance=True”;
      hay là lưu trữ chuỗi kết nối trong file app.config?

      • Sơn viết:

        E đang dùng kết chuỗi kết nối như thầy hướng dẫn ở bên trên
        Lưu trữ chuỗi kết nối trong file app.config ạ

        • Phan Tiến viết:

          Em mở file app.config xem cấu của em có giống như thế này không:
          connectionString=”Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\QLBanHang.mdf;Integrated Security=True;User Instance=True”
          Nếu giống thì em có thể làm các cách như sau
          Cách 1: thay thế |DataDirectory|\QLBanHang.mdf bằng đường dẫn thực đến CSDL của bạn, ví dụ: C:\DB\QLBanHang.mdf
          Cách 2: Trong cửa sổ Solution Explorer > chọn vào DataBase QLBanHang.mdf > xuất hiện cửa sổ Property > phần Copy to Output Directory> chọn Copy to newer

  2. Trần Hoàng Giang viết:

    Có 1 lưu ý cho các bạn, ở đoạn thầy viết con.ConnectionString =
    Có sử dụng đường dẫn động Application.StartupPath, nhưng khi chạy debug thử thì file .mdf nằm trong thư mục bin/debug chứ ko sử dụng file do mình tạo ra ở thư mục chính của project.

    Trong màn hình Visual Studio ở phần Server Explorer thì nó lại hiện file ở thư mục chính của Project vì vậy khi ta chuột phải vào Table chọn Show Table Data sẽ ko thấy dữ liệu mình vừa thêm vào đâu cả, vì thực chất nó ko thêm vào file đó.

  3. hà huế viết:

    // Khao báo đối Tượng connection
    SqlConnection con = new SqlConnection();
    con.ConnectionString = @”Data Source=.\SQLEXPRESS;AttachDbFilename=D:\web\BaiTapLon\BaiTapLon\QuanLySach.mdf;Integrated Security=True;User Instance=True”;
    con.Open();
    // Viết câu lệnh truy vấn
    String sql = “SELECT * FROM tblMatHang”;
    DataSet ds = new DataSet();
    SqlDataAdapter dap = new SqlDataAdapter(sql, con);
    dap.Fill(ds);
    //Gắn Dữ Liệu Lên datagrid
    dgvMatHang.DataSource = ds.Tables[0];
    dgv.refresh();
    }
    thầy ơi lỗi báo k có dvg.MatHang cái dvgMatHang tạo ở đâu thế ạ

  4. Andy viết:

    Chào thầy! cảm ơn thầy đã tạo ra hướng dẫn mà em đang cần
    1/ em đã làm như được hướng dẫn tuy nhiên ở phần Solution explorer không hiển thị như giao diện của thầy (em dùng visual studio 2017, Solusion Explorer không có phần QLBanHangDataSet.xsd).
    2/ Sau khi tạo bảng chương trình yêu câu lưu ở định dạng xxx.sql, ở mục server explorer\ table không thấy bảng vừa tạo mặc dù file xxx.sql lưu cùng 1 đường dẫn.

  5. Andy viết:

    Chào Thầy.
    Trường hợp e tao sẳn các bảng dạng *.dbf (lưu sẳn ở 1 thư mục mặt định). việc kết nối file sẽ như thế nào hả thầy.có thể Kết nối bằng dialog để open 1 cái path. Mong thầy chỉ giúp

    • Phan Tiến viết:

      Có thể làm được, khi em mở dialog ra và lấy đường dẫn đến file *.mdf của em.
      Ví dụ như đoạn code dưới:
      void showData(string path)
      {

      String strConnection = @”Data Source=.\SQLEXPRESS;
      AttachDbFilename=” + path + “;” +
      “Integrated Security=True;” +
      “Connect Timeout=30;” +
      “User Instance=False”;
      SqlConnection con = new SqlConnection(strConnection);
      …………
      }

      Biến path em có thể lấy từ dialog và truyền vào showData(path).

  6. Thoáng viết:

    Thưa thầy! EM đang dùng bản Visual Studio 2010! Tạo Database hư trên nhưng đến bước Add new table thì nó hiễn Thông báo là ” This server version is not supported. Only Servers up to MS SQL server 2008 are supported” Em phải khắc phục như thế nào ạ??

  7. Huyền viết:

    Thưa thầy!
    Sai ở chỗ cmd.ExecuteNonQuery(); là lõi ở đâu ạ

  8. Huy01212 viết:

    Thưa thầy, Em bị lỗi ở
    dap.Fill(ds);
    Nó báo lỗi này thì phải làm sao ạ?
    instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)’

  9. Dung viết:

    thưa thầy làm sao để phần hiện dữ liệu của datagritview tự động điều chỉnh độ rộng phù hợp vs cửa sổ khi mở rộng ra mà k bị lơ lửng ạ.
    em cảm ơn ạ.

  10. quy viết:

    thay co the huong dan em xoa 1 day cai list da chon trong DataGridView , va xoas no trong csdl luon a

  11. adora viết:

    thưa thầy, làm sao có thể sử dụng hàm mà trả giá trị bảng trong C# được ạ

  12. Mỹ Tiên viết:

    private void cmbMS_SelectedIndexChanged(object sender, EventArgs e)
    {
    cmbNgayKeDon.Items.Clear();
    string t=cmbMS.Text.Trim();
    string sQuerycmbNgay = “select DISTINCT hdt.mabn, ngaysudung from HoaDonThuoc hdt”;
    sQuerycmbNgay += “where mabn='”+ cmbMS.SelectedValue +”‘”;
    daQLNg = new SqlDataAdapter(sQuerycmbNgay, conn);
    daQLNg.Fill(ds, “tblNgay”);
    cmbNgayKeDon.DataSource = ds.Tables[“tblNgay”];
    cmbNgayKeDon.DisplayMember = “ngaysudung”;
    cmbNgayKeDon.ValueMember = “ngaysusung”;
    }
    Em muốn khi thay đổi dữ liệu ở combobox cmbMS thì dữ liệu trong combobox cmbNgayKeDon thay đổi theo. Code không báo lỗi nhưng em chạy thì cmbNgayKeDon không hiển thị giá trị. Nhờ thầy chỉ giúp.

  13. Hiếu viết:

    chào thầy ạ! Em có khó khăn cần giúp ạ. Hiện e có 1 bảng dl lớp(có tổng số ngày học -songay, ngày bđ- ngaybd(dd,mm,yyyy), ngày kt – ngaykt), em muốn dùng thuật toán tham lam để sắp lớp dựa trên tỏng số ngày học, khóa ngắn ngày sắp trc, em ko bt truy vấn sao bên C#, mong thầy giúp ạ

  14. Đăng Quang viết:

    Thầy ơi em chạy được rồi nhưng khi bấm thêm thì nó lại thông báo lỗi ở cmd.ExecuteNonQuery(); ạ

  15. Hung Dinh viết:

    System.Data.SqlClient.SqlException
    HResult=0x80131904
    Message=Conversion failed when converting date and/or time from character string.
    Source=.Net SqlClient Data Provider
    StackTrace:

    Em cũng bi lỗi giống bạn Đăng Quang, nhờ thầy sữa dùm lỗi này.

Trả lời

EnglishVietnamese