Dapper trong .NET Core là gì? Hướng dẫn CRUD và EF Core
Dapper trong .NET Core là gì? Tìm hiểu micro ORM, cách cài đặt, ví dụ CRUD bằng C#, chống SQL Injection và so sánh Dapper với Entity Framework Core.
Dapper trong .NET Core là một thư viện micro ORM giúp thực thi SQL và ánh xạ kết quả thành đối tượng C#. Bạn chủ động viết câu truy vấn, còn Dapper giảm phần mã lặp lại khi truyền tham số và đọc dữ liệu. Đây là lựa chọn đáng tìm hiểu nếu bạn đã biết SQL và muốn xây dựng lớp truy cập dữ liệu gọn, dễ kiểm soát. Bài viết này giải thích Dapper là gì, hướng dẫn một ví dụ CRUD chạy được, so sánh với Entity Framework Core và chỉ ra những lỗi thường gặp. Thuật ngữ “.NET Core” vẫn phổ biến khi tìm kiếm; ví dụ bên dưới sử dụng .NET 8, thuộc dòng .NET hiện đại. Xem hướng dẫn cài .NET SDK của Microsoft nếu bạn chưa có môi trường phát triển. 1. Dapper là gì và hoạt động như thế nào? ORM là cách làm việc với dữ liệu quan hệ thông qua đối tượng trong chương trình. Dapper tập trung vào một phạm vi nhỏ: chạy lệnh trên kết nối ADO.NET và chuyển các cột kết quả thành thuộc tính của đối tượng. Vì vậy, nó được gọi là micro ORM . Bạn vẫn chịu trách nhiệm về SQL và cấu trúc database. Thư viện được phát triển ban đầu cho Stack Overflow và được phân phối mã nguồn mở trên NuGet. Tham khảo trang gói Dapper . Luồng cơ bản có thể hình dung như sau: Đối tượng tham số C# → câu SQL → database → các dòng kết quả → đối tượng C#. Chẳng hạn, câu lệnh chọn các cột Id , Name và PriceVnd có thể trả về một đối tượng Product với các thuộc tính tương ứng. Khi tên cột khác tên thuộc tính, bạn có thể dùng bí danh SQL để ánh xạ rõ ràng. 2. Ưu điểm và giới hạn của Dapper SQL rõ ràng: người đọc thấy trực tiếp điều kiện lọc, phép nối và các cột được lấy. Giảm mã ADO.NET lặp lại: bớt thao tác tạo tham số, đọc từng cột và tự gán vào đối tượng. Phạm vi nhỏ: thuận tiện cho đội ngũ muốn tự quản lý truy vấn và tối ưu theo database đang dùng. Cần biết SQL: sai điều kiện cập nhật hoặc truy vấn thiếu chỉ mục vẫn gây lỗi và chậm như bình thường. Dapper lõi không tự cung cấp toàn bộ quy trình như migrations hay cơ chế theo dõi thay đổi tương đương EF Core. Đọc một đối tượng rồi sửa thuộc tính trong bộ nhớ không có nghĩa database đã được cập nhật: bạn cần thực thi câu UPDATE . Đừng nhầm thư viện lõi với các gói mở rộng bổ sung tiện ích khác. 3. Cài đặt Dapper trong dự án .NET Để tập trung vào cách dùng Dapper, chúng ta tạo một Console App .NET 8 với SQLite. Bạn không cần cài riêng SQL Server để chạy thử. Mở terminal và thực hiện: dotnet new console -n DapperDemo -f net8.0 cd DapperDemo dotnet add package Dapper --version 2.1.89 dotnet add package Microsoft.Data.Sqlite --version 8.0.31 Phiên bản được ghim để ví dụ dễ tái lập; khi đưa vào dự án thật, hãy chọn và kiểm tra phiên bản phù hợp với target framework của bạn. Dapper và thư viện kết nối database là hai thành phần khác nhau: ở đây, Microsoft.Data.Sqlite tạo kết nối SQLite, còn Dapper hỗ trợ thực thi SQL và ánh xạ dữ liệu. Xem gói provider SQLite dùng trong ví dụ . 4. Ví dụ CRUD với Dapper bằng C# Thay toàn bộ nội dung Program.cs bằng đoạn sau. Ví dụ tạo bảng sản phẩm, thêm dữ liệu, đọc theo ID, cập nhật giá và xóa sản phẩm. Giá được biểu diễn bằng số nguyên VND để tránh làm phần nhập môn phức tạp vì cách xử lý số thập phân. using Dapper; using Microsoft.Data.Sqlite; using var connection = new SqliteConnection("Data Source=:memory:"); connection.Open(); connection.Execute(""" CREATE TABLE Products ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT NOT NULL, PriceVnd INTEGER NOT NULL CHECK (PriceVnd >= 0) ); """); // Create: insert and return the generated ID on this connection. long id = connection.ExecuteScalar<long>(""" INSERT INTO Products (Name, PriceVnd) VALUES (@Name, @PriceVnd); SELECT last_insert_rowid(); """, new { Name = "Sach C#", PriceVnd = 150_000L }); // Read: return null when the product does not exist. Product? product = connection.QuerySingleOrDefault<Product>( "SELECT Id, Name, PriceVnd FROM Products WHERE Id = @Id;", new { Id = id }); Console.WriteLine($"Read: {product?.Name} - {product?.PriceVnd} VND"); // Update: check the affected row count. int updated = connection.Execute( "UPDATE Products SET PriceVnd = @PriceVnd WHERE Id = @Id;", new { Id = id, PriceVnd = 120_000L }); Console.WriteLine($"Updated rows: {updated}"); // Delete: pass IDs as parameters rather than joining them into SQL. int deleted = connection.Execute( "DELETE FROM Products WHERE Id = @Id;", new { Id = id }); Console.WriteLine($"Deleted rows: {deleted}"); public sealed class Product { public long Id { get; set; } public string Name { get; set; } = string.Empty; public long PriceVnd { get; set; } } Chạy chương trình: dotnet run Kết quả dự kiến: Read: Sach C# - 150000 VND Updated rows: 1 Deleted rows: 1 Điểm cần chú ý là Data Source=:memory: tạo database trong bộ nhớ. Kết nối được giữ mở suốt ví dụ; dữ liệu mất khi đóng kết nối. Cách này phù hợp để thử CRUD và không phải cách lưu dữ liệu lâu dài cho ứng dụng thực tế. Ý nghĩa các phương thức trong ví dụ Execute : thực thi lệnh thêm, sửa hoặc xóa; trả về số dòng bị tác động trong trường hợp thông thường. Query<T> : lấy nhiều dòng và ánh xạ thành các đối tượ…