VieTopikKhoá học
  • Games
  • Cá nhân
Tải app
© 2026 VieTopikChính sách bảo mậtĐiều khoản sử dụngCài appEnglish
  • Trang chủ
  • Học
  • Luyện thi
  • Cẩm nang
  • Games
  • Cá nhân
WinForms với OracleKết nối Oracle
Bài 11/15
6 phút

CRUD với DataGridView

Bình luận
Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Màn hình kho mới chỉ xem được. Nhân viên cần sửa giá, thêm sản phẩm mới, xoá sản phẩm ngừng bán ngay trên lưới, rồi bấm một nút để ghi hết xuống Oracle.

Khái niệm

👀 Change tracking (theo dõi thay đổi): DbContext ghi nhớ mọi object nó đã đọc ra hoặc được thêm vào, và biết object nào mới, bị sửa hay bị xoá.

🪝 Local.ToBindingList(): method trả về danh sách các object của một DbSet mà DbContext đang theo dõi, gắn được vào BindingSource.

Thêm hay xoá dòng trên lưới gắn với danh sách này thì DbContext biết ngay.

SaveChangesAsync đã gặp ở khoá ASP.NET Core. Nó biến những thay đổi đang ghi nhớ thành câu INSERT, UPDATE, DELETE, rồi chạy chúng trong một transaction như bài Transaction của khoá SQL.

Ví dụ

using Microsoft.EntityFrameworkCore;

class MainForm : Form
{
    private readonly ShopDbContext _db;
    private readonly BindingSource _source =
        new BindingSource();
    private readonly Button _saveButton = new Button
    {
        Text = "Lưu",
        Dock = DockStyle.Top
    };

    public MainForm(ShopDbContext db)
    {
        _db = db;
        Text = "Kho hàng";
        Width = 500;

        var grid = new DataGridView
        {
            Dock = DockStyle.Fill,
            DataSource = _source
        };
        grid.DataBindingComplete += (sender, e) =>
        {
            grid.Columns[0].ReadOnly = true;
        };
        Controls.Add(grid);
        Controls.Add(_saveButton);

        Load += async (sender, e) =>
        {
            await _db.Products.LoadAsync();
            _source.DataSource =
                _db.Products.Local.ToBindingList();
        };
        _saveButton.Click += SaveButton_Click;
    }

    private async void SaveButton_Click(
        object? sender, EventArgs e)
    {
        _saveButton.Enabled = false;
        try
        {
            int count = await _db.SaveChangesAsync();
            Text = $"Đã lưu {count} thay đổi";
        }
        finally
        {
            _saveButton.Enabled = true;
        }
    }
}
  • Lưới bỏ ReadOnly và giữ dòng trống cuối. Sửa ngay trong ô, gõ vào dòng trống để thêm. Muốn xoá, bấm ô xám đầu dòng để chọn cả dòng rồi bấm phím Delete.
  • LoadAsync() đọc bảng vào DbContext. Local.ToBindingList() đưa các object đó lên lưới.
  • finally bật lại nút dù lưu thành công hay lỗi, như bài Exception của khoá C# Core.
  • Cột Id (cột 0) chỉ đọc, vì Oracle tự sinh khoá chính.
  • SaveChangesAsync trả về số dòng đã ghi.
sửa, thêm, xoá SaveChangesAsync Lưới DbContext ghi nhớ Oracle
Lưới nối với DbContext, chỉ SaveChangesAsync mới ghi xuống Oracle

Thử ngay

Chạy app. Sửa giá một sản phẩm, gõ thêm một sản phẩm mới ở dòng trống cuối, chọn cả dòng "Balo" rồi bấm Delete. Sau đó bấm "Lưu".

Đoán trước khi chạy: tiêu đề báo đã lưu mấy thay đổi, và đó là những thay đổi gì?

Xem kết quả
Đã lưu 3 thay đổi

Ba thay đổi này thành một UPDATE, một INSERT và một DELETE trong Oracle. Trước khi bấm "Lưu", mọi thay đổi chỉ nằm trong bộ nhớ của DbContext. Đóng app lúc đó thì Oracle không nhận được gì, giống transaction chưa COMMIT.

Lỗi hay gặp

Gắn lưới vào ToListAsync(). Sửa ô vẫn được lưu, vì DbContext đang theo dõi các object đó. Còn thêm hay xoá dòng trên lưới chỉ làm đổi một list thường, DbContext không biết nên SaveChangesAsync bỏ qua.

// SAI — thêm, xoá trên lưới không được lưu
_source.DataSource =
    await _db.Products.ToListAsync();
// ĐÚNG — lưới nối thẳng với DbContext
await _db.Products.LoadAsync();
_source.DataSource =
    _db.Products.Local.ToBindingList();

Để trống tên sản phẩm mới. Oracle coi chuỗi rỗng là NULL, như bài NULL trong SQL của khoá SQL. Cột NAME là NOT NULL, nên SaveChangesAsync ném DbUpdateException với mã ORA-01400. Không có finally thì nút "Lưu" bị tắt luôn sau lần lỗi đó.

Tóm tắt

  • DbContext theo dõi object mới, bị sửa, bị xoá (change tracking).
  • LoadAsync() rồi gắn Local.ToBindingList() để lưới nối thẳng với DbContext.
  • SaveChangesAsync ghi mọi thay đổi trong một transaction, trả về số dòng.
  • Chưa SaveChangesAsync thì Oracle chưa nhận gì.
Async giữ giao diện mượtMaster-detail

Bình luận

Đang tải bình luận…

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt