Kết nối Winform với SQL Server

Hướng dẫn thực hành kết nối từ A-Z kết nối Winform với SQL Server, có bài tập, video thực hành trong khóa học winform từ cơ bản đến nâng cao.

  1. Video thực hành kết nối winform với SQL dễ hiểu nhất
  2. Thêm thư viện với SQL Server
  3. Chuỗi kết nối SQL Server (Connection String)
  4. Kết nối và truy vấn chi tiết từ winform đến SQL Server
  5. Những lưu ý khi kết nối từ winform đến SQL Server
  6. Chia sẽ kinh nghiệm kết nối winform với SQL Server

Để kết nối WinForms (Windows Forms Application) với SQL Server, bạn thực hiện theo các bước dưới đây

1. Video thực hành kết nối winform với SQL dễ hiểu nhất

2. Thêm thư viện với SQL Server

WinForms dùng ADO.NET để kết nối, cần System.Data.SqlClient:

using System.Data;
using System.Data.SqlClient;

3. Chuỗi kết nối SQL Server (Connection String)

Dạng cơ bản:

string connectionString = "Server=TEN_SERVER;Database=TEN_CSDL;User Id=USERNAME;Password=MATKHAU;";

Ví dụ sử dụng SQL Server Authentication:

string connectionString = "Server=localhost;Database=QLSV;User Id=sa;Password=123;";

Ví dụ dùng Windows Authentication:

string connectionString = "Server=localhost;Database=QLSV;Integrated Security=True;";

4. Kết nối và truy vấn chi tiết từ winform đến SQL Server

 Ví dụ: Kết nối và đọc dữ liệu từ bảng SinhVien

using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;

namespace DemoConnectSQL
{
    public partial class Form1 : Form
    {
        string connectionString = "Server=localhost;Database=QLSV;Integrated Security=True;";

        public Form1()
        {
            InitializeComponent();
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                try
                {
                    conn.Open();

                    string sql = "SELECT * FROM SinhVien";
                    SqlDataAdapter da = new SqlDataAdapter(sql, conn);
                    DataTable dt = new DataTable();
                    da.Fill(dt);

                    dataGridView1.DataSource = dt;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Lỗi kết nối: " + ex.Message);
                }
            }
        }
    }
}

5. Những lưu ý khi kết nối từ winform đến SQL Server

    Đảm bảo SQL Server đang chạy.

    Tên server có thể là:

        localhost:  . (chấm)
        MAYTINH\SQLEXPRESS (nếu bạn cài bản SQL Server Express)
    Nên kiểm tra SQL bằng SQL Server Management Studio trước.

6. Chia sẽ kinh nghiệm kết nối winform với SQL Server

    Để làm phần mềm thương mại, hay nhiều thành viên làm phần mềm winform cần chú ý các vấn đề sau.

    Dùng using để tự động giải phóng tài nguyên.

Khi bạn dùng kết nối với SQL Server (hoặc thao tác với bất kỳ tài nguyên nào như file, stream, v.v...), bạn nên sử dụng using để đảm bảo tự động giải phóng tài nguyên sau khi dùng xong.

✅ Lý do dùng using

Các đối tượng như SqlConnection, SqlCommand, SqlDataReader là các đối tượng quản lý tài nguyên hệ thống (mạng, bộ nhớ, handle...). Nếu bạn không giải phóng, ứng dụng dễ bị rò rỉ bộ nhớ hoặc khóa tài nguyên.

using giúp đảm bảo gọi Dispose() tự động, dù có lỗi xảy ra hay không.

📌 Cú pháp using

using (var obj = new SomeDisposableObject())
{
    // code sử dụng obj
} // -> tự động gọi obj.Dispose() khi ra khỏi khối

✅ Ví dụ thực tế: Không dùng using ❌

SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM SinhVien", conn);
SqlDataReader reader = cmd.ExecuteReader();

// Xử lý dữ liệu...

reader.Close();
conn.Close();

➡️ Nhược điểm: Nếu xảy ra lỗi trước khi gọi Close(), tài nguyên sẽ không được giải phóng.

✅ Dùng using ✔️

using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (SqlCommand cmd = new SqlCommand("SELECT * FROM SinhVien", conn))
    {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                string ten = reader["TenSV"].ToString();
                // xử lý...
            }
        }
    }
}

➡️ Ưu điểm:

    Dù có lỗi xảy ra, các đối tượng vẫn được tự động đóng và giải phóng.
    Code gọn gàng, rõ ràng.

✅ Khi nào using có tác dụng?

Khi đối tượng implement IDisposable, ví dụ:
    SqlConnection
    SqlCommand
    SqlDataReader
    FileStream
    StreamReader
    MemoryStream

✅ Gợi ý nâng cao

Bạn có thể lồng nhiều using hoặc gộp chung:

using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand("SELECT * FROM SV", conn))
{
    conn.Open();
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        // xử lý
    }
}

   Sử dụng SqlParameter để tránh SQL Injection.

   Đây là một kỹ thuật rất quan trọng để bảo mật ứng dụng khi kết nối với SQL Server:

✅ Sử dụng SqlParameter để tránh SQL Injection

❗ Vấn đề: SQL Injection là gì?

SQL Injection là một lỗ hổng bảo mật nghiêm trọng cho phép kẻ tấn công chèn mã SQL độc hại vào câu lệnh truy vấn thông qua input người dùng.

❌ Ví dụ nguy hiểm:

string user = txtUser.Text;
string pass = txtPass.Text;

string sql = "SELECT * FROM TaiKhoan WHERE UserName = '" + user + "' AND Password = '" + pass + "'";

Nếu người dùng nhập:

User: admin
Pass: ' OR '1'='1

Thì câu SQL sẽ thành:

SELECT * FROM TaiKhoan WHERE UserName = 'admin' AND Password = '' OR '1'='1'

➡️ Kết quả: Đăng nhập thành công không cần mật khẩu ❌
✅ Giải pháp: Dùng SqlParameter

🔐 Cách an toàn để không bị hack:

string user = txtUser.Text;
string pass = txtPass.Text;

string sql = "SELECT * FROM TaiKhoan WHERE UserName = @user AND Password = @pass";

using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
    cmd.Parameters.AddWithValue("@user", user);
    cmd.Parameters.AddWithValue("@pass", pass);

    conn.Open();
    SqlDataReader reader = cmd.ExecuteReader();

    if (reader.HasRows)
    {
        MessageBox.Show("Đăng nhập thành công");
    }
    else
    {
        MessageBox.Show("Sai tài khoản hoặc mật khẩu");
    }
}

✅ Giải thích:

    @user, @pass: là tên tham số trong câu lệnh SQL.
    cmd.Parameters.AddWithValue(...): gán giá trị input một cách an toàn.

    SqlParameter sẽ tự động:

        Escape ký tự nguy hiểm (', --, ;, ...)
        Chống injection
        Tự kiểm tra kiểu dữ liệu

📌 Có thể viết rõ kiểu hơn:

cmd.Parameters.Add(new SqlParameter("@user", SqlDbType.VarChar) { Value = user });

✅ Ưu điểm:

Ưu điểm    Lý do
An toàn    Tránh được SQL Injection
Tối ưu hóa hiệu suất    SQL Server cache câu lệnh có tham số dễ hơn
Rõ ràng, dễ bảo trì    Không cần nối chuỗi phức tạp

✅ Một ví dụ khác: Insert dữ liệu

string sql = "INSERT INTO SinhVien (MaSV, TenSV, Lop) VALUES (@ma, @ten, @lop)";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
    cmd.Parameters.AddWithValue("@ma", txtMa.Text);
    cmd.Parameters.AddWithValue("@ten", txtTen.Text);
    cmd.Parameters.AddWithValue("@lop", cboLop.Text);
    cmd.ExecuteNonQuery();
}

Có thể viết lớp DBHelper để tái sử dụng lệnh SQL.

Việc tạo một lớp DBHelper giúp bạn:

✅ Tái sử dụng kết nối và xử lý SQL
✅ Code gọn gàng, dễ bảo trì
✅ Tách riêng phần truy cập dữ liệu khỏi giao diện WinForms
✅ Mục tiêu của DBHelper:

    Mở kết nối
    Thực thi lệnh SELECT, INSERT, UPDATE, DELETE
    Hỗ trợ SqlParameter
    Dùng using để tự động giải phóng

✅Tạo lớp DBHelper.cs

using System;
using System.Data;
using System.Data.SqlClient;
public static class DBHelper
{
    private static string connectionString = "Server=localhost;Database=QLSV;Integrated Security=True;";

    // Hàm SELECT, trả về DataTable
    public static DataTable GetData(string sql, params SqlParameter[] parameters)
    {
        DataTable dt = new DataTable();

        using (SqlConnection conn = new SqlConnection(connectionString))
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            if (parameters != null)
                cmd.Parameters.AddRange(parameters);

            conn.Open();
            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                dt.Load(reader);
            }
        }

        return dt;
    }

    // Hàm thực thi INSERT, UPDATE, DELETE (trả về số dòng ảnh hưởng)
    public static int Execute(string sql, params SqlParameter[] parameters)
    {
        int affectedRows = 0;

        using (SqlConnection conn = new SqlConnection(connectionString))
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            if (parameters != null)
                cmd.Parameters.AddRange(parameters);

            conn.Open();
            affectedRows = cmd.ExecuteNonQuery();
        }

        return affectedRows;
    }

    // Hàm lấy một giá trị đơn (ví dụ SELECT COUNT(*) hoặc MAX...)
    public static object GetScalar(string sql, params SqlParameter[] parameters)
    {
        using (SqlConnection conn = new SqlConnection(connectionString))
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            if (parameters != null)
                cmd.Parameters.AddRange(parameters);

            conn.Open();
            return cmd.ExecuteScalar();
        }
    }
}

✅ Cách sử dụng lớp DBHelper

📌 Ví dụ 1: Load dữ liệu vào DataGridView

string sql = "SELECT * FROM SinhVien WHERE Lop = @lop";
var dt = DBHelper.GetData(sql, new SqlParameter("@lop", "12A1"));
dataGridView1.DataSource = dt;

📌 Ví dụ 2: Thêm sinh viên

string sql = "INSERT INTO SinhVien (MaSV, TenSV, Lop) VALUES (@ma, @ten, @lop)";
int result = DBHelper.Execute(sql,
    new SqlParameter("@ma", txtMa.Text),
    new SqlParameter("@ten", txtTen.Text),
    new SqlParameter("@lop", cboLop.Text)
);
MessageBox.Show(result > 0 ? "Thêm thành công" : "Thêm thất bại");

📌 Ví dụ 3: Lấy tổng số sinh viên

string sql = "SELECT COUNT(*) FROM SinhVien";
int total = Convert.ToInt32(DBHelper.GetScalar(sql));
lblTong.Text = "Tổng SV: " + total;

Tìm kiếm:

Hướng dẫn thực hành kết nối từ A-Z kết nối Winform với SQL Server, có bài tập, video thực hành trong khóa học winform từ cơ bản đến nâng cao.