1. Giới thiệu Entity Framework
Entity Framework là một framework (khung) của Microsoft hỗ trợ phát triển ứng dụng .NET để làm việc với cơ sở dữ liệu liên quan đến đối tượng (object-relational mapping - ORM). Entity Framework cung cấp cho các lập trình viên một cách tiếp cận trừu tượng hóa cơ sở dữ liệu (abstraction layer) giúp giảm thiểu sự phức tạp khi phát triển ứng dụng.
Entity Framework cho phép bạn tạo các đối tượng .NET và ánh xạ chúng sang cơ sở dữ liệu. Nó hỗ trợ nhiều loại cơ sở dữ liệu, bao gồm SQL Server, MySQL, Oracle và PostgreSQL. Entity Framework cũng hỗ trợ lập trình truy vấn LINQ (Language Integrated Query) giúp cho việc truy vấn cơ sở dữ liệu trở nên dễ dàng hơn và đơn giản hơn.
Entity Framework là một phần của .NET Framework và được tích hợp sẵn trong Visual Studio, cho phép lập trình viên tạo, quản lý và truy vấn cơ sở dữ liệu một cách dễ dàng hơn. Bằng cách sử dụng Entity Framework, lập trình viên có thể tập trung vào việc thiết kế ứng dụng và tạo đối tượng, thay vì phải quản lý các câu truy vấn cơ sở dữ liệu phức tạp.
2. Giới thiệu Database-first
Database-first là một phương pháp thiết kế cơ sở dữ liệu trong Entity Framework. Phương pháp này cho phép tạo các class và đối tượng của ứng dụng từ cơ sở dữ liệu tồn tại. Database-first cung cấp khả năng tạo model Entity Framework từ cơ sở dữ liệu, cho phép bạn dễ dàng tạo, đọc, cập nhật và xóa dữ liệu từ database.
Trong Database-first, các đối tượng và class được tạo tự động bằng cách đọc cấu trúc của cơ sở dữ liệu. Việc tạo đối tượng có thể được thực hiện thông qua công cụ Visual Studio hoặc dòng lệnh, và sau đó mô hình EF có thể được sử dụng để thực hiện các thao tác CRUD với cơ sở dữ liệu.
Phương pháp Database-first rất hữu ích khi bạn đã có một cơ sở dữ liệu tồn tại và bạn muốn sử dụng Entity Framework để quản lý dữ liệu. Tuy nhiên, nó có thể gặp khó khăn trong việc tạo các đối tượng đầy đủ trong ứng dụng của bạn nếu cơ sở dữ liệu của bạn phức tạp và có nhiều bảng liên kết.
3. Giới thiệu Code-first
Code-first là một phương pháp trong Entity Framework cho phép lập trình viên tạo cấu trúc cơ sở dữ liệu và các đối tượng liên quan trong mã nguồn của mình. Với Code-first, lập trình viên có thể định nghĩa các lớp đối tượng trong mã nguồn, Entity Framework sẽ tự động tạo các bảng và các khóa ngoại trong cơ sở dữ liệu dựa trên các lớp đó.
Khi sử dụng Code-first, lập trình viên cần sử dụng các thuộc tính để chỉ định các mối quan hệ giữa các lớp đối tượng, cũng như các thuộc tính để chỉ định các ràng buộc và các thuộc tính của cột trong cơ sở dữ liệu.
Code-first cho phép lập trình viên linh hoạt hơn trong việc quản lý cơ sở dữ liệu và các đối tượng trong mã nguồn, đồng thời cũng cung cấp khả năng kiểm soát và theo dõi rõ ràng hơn đối với các thay đổi cơ sở dữ liệu.
4. Cách thức làm việc với Entity Framework
Trong ASP.NET MVC, Entity Framework (EF) được sử dụng để tương tác với cơ sở dữ liệu. Các bước để sử dụng EF trong ASP.NET MVC như sau:
- Tạo project ASP.NET MVC: Để tạo project, bạn có thể chọn "ASP.NET Web Application" trong Visual Studio và chọn "Empty" hoặc "Web API" template.
- Cài đặt Entity Framework: Sử dụng Package Manager Console để cài đặt Entity Framework qua lệnh sau:
Install-Package EntityFramework
- Tạo Model: EF cho phép ta sử dụng Code-first hoặc Database-first để tạo Model. Trong Code-first, bạn có thể tạo Model trực tiếp từ các Class. Trong Database-first, Model được tạo dựa trên cơ sở dữ liệu hiện tại.
- Tạo DbContext: DbContext là đối tượng chịu trách nhiệm quản lý Model và tương tác với cơ sở dữ liệu. Bạn có thể tạo lớp kế thừa từ DbContext và khai báo các DbSet để tương tác với các bảng trong cơ sở dữ liệu.
- Thực hiện các thao tác CRUD: Sử dụng các phương thức của DbSet như Add, Update, Delete để thực hiện các thao tác CRUD với cơ sở dữ liệu.
- Sử dụng Dependency Injection: Để sử dụng EF trong MVC, ta có thể sử dụng Dependency Injection. Thông thường, ta sẽ đăng ký DbContext trong hệ thống Dependency Injection của MVC bằng cách sử dụng các Container như Autofac, Ninject, Unity,...
- Sử dụng LINQ để truy vấn dữ liệu: Sử dụng LINQ để truy vấn dữ liệu từ cơ sở dữ liệu thông qua DbContext. Các phương thức của DbSet, chẳng hạn như Where, OrderBy, Select,.. được sử dụng để tạo các truy vấn LINQ. Kết quả trả về là một đối tượng IQueryable có thể được lặp lại để truy xuất các kết quả của truy vấn.
5. Cách thức thực thi Code-first
Để thực thi Code-first trong ASP.NET MVC, bạn cần thực hiện các bước sau:
- Bước 1: Tạo một lớp model để biểu diễn cho cơ sở dữ liệu, ví dụ:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
}
- Bước 2: Tạo một lớp kế thừa từ DbContext để quản lý các thao tác với cơ sở dữ liệu, ví dụ:
public class ApplicationDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
}
- Bước 3: Cấu hình chuỗi kết nối trong file Web.config, ví dụ:
<connectionStrings>
<add name="ApplicationDbContext" connectionString="Server=(localdb)\MSSQLLocalDB;Database=MyDatabase;Trusted_Connection=True;MultipleActiveResultSets=true" providerName="System.Data.SqlClient" />
</connectionStrings>
- Bước 4: Thực hiện các thao tác CRUD (Create, Read, Update, Delete) với cơ sở dữ liệu trong ASP.NET MVC Controller, ví dụ:
public class ProductController : Controller
{
private readonly ApplicationDbContext _context;
public ProductController(ApplicationDbContext context)
{
_context = context;
}
public IActionResult Index()
{
var products = _context.Products.ToList();
return View(products);
}
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create(Product product)
{
_context.Products.Add(product);
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
public IActionResult Edit(int id)
{
var product = _context.Products.Find(id);
return View(product);
}
[HttpPost]
public IActionResult Edit(Product product)
{
_context.Products.Update(product);
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
public IActionResult Delete(int id)
{
var product = _context.Products.Find(id);
return View(product);
}
[HttpPost, ActionName("Delete")]
public IActionResult DeleteConfirmed(int id)
{
var product = _context.Products.Find(id);
_context.Products.Remove(product);
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
}
Trong đó, hàm tạo của ProductController nhận vào đối tượng của ApplicationDbContext để có thể truy cập vào cơ sở dữ liệu. Các thao tác CRUD đều được thực hiện thông qua đối tượng của ApplicationDbContext. Ví dụ trên chỉ là một số thao tác cơ bản, bạn có thể mở rộng để thực hiện các thao tác phức tạp hơn.
6. Lớp DbContext
Trong Entity Framework, lớp DbContext là lớp chính để quản lý truy cập cơ sở dữ liệu và thực hiện các thao tác CRUD (tạo, đọc, cập nhật, xóa) trên đối tượng của ứng dụng. Dưới đây là một ví dụ cụ thể về cách sử dụng lớp DbContext trong ASP.NET MVC:
- Ta có một ứng dụng quản lý sách, cần kết nối tới cơ sở dữ liệu và thực hiện các thao tác CRUD trên bảng Sách. Đầu tiên, ta tạo một lớp Sách để mô tả thông tin sách:
public class Sach
{
public int Id { get; set; }
public string TenSach { get; set; }
public string TacGia { get; set; }
public int NamXuatBan { get; set; }
}
- Tiếp theo, ta tạo một lớp kế thừa từ DbContext để quản lý truy cập đến bảng Sách trong cơ sở dữ liệu:
public class SachDbContext : DbContext
{
public DbSet<Sach> DanhSachSach { get; set; }
}
- Lớp SachDbContext kế thừa từ lớp DbContext và định nghĩa một thuộc tính DanhSachSach kiểu DbSet để đại diện cho bảng Sách trong cơ sở dữ liệu. Sau đó, ta cần cấu hình chuỗi kết nối đến cơ sở dữ liệu trong tệp web.config của ứng dụng:
<connectionStrings>
<add name="SachDbContext" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=QuanLySach;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
- Cuối cùng, ta có thể sử dụng lớp SachDbContext trong các action của controller để thực hiện các thao tác CRUD trên bảng Sách, ví dụ:
public class SachController : Controller
{
private SachDbContext db = new SachDbContext();
public ActionResult Index()
{
var danhSachSach = db.DanhSachSach.ToList();
return View(danhSachSach);
}
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Sach sach)
{
if (ModelState.IsValid)
{
db.DanhSachSach.Add(sach);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(sach);
}
// Các action khác tương tự
}
Ở ví dụ trên, trong action Index, ta sử dụng lớp SachDbContext để lấy danh sách các sách từ cơ sở dữ liệu và truyền vào view. Trong action Create, ta thêm một sách mới vào cơ sở dữ liệu bằng cách sử dụng đối tượng db của lớp SachDbContext. Cuối cùng, trong action Edit, ta lấy sách từ cơ sở dữ liệu và gán giá trị của sách cần chỉnh sửa vào đối tượng sách này. Sau đó, ta lưu thay đổi vào cơ sở dữ liệu bằng phương thức SaveChanges của đối tượng db."
Trong action Edit, chúng ta cũng sử dụng lớp SachDbContext để lấy sách từ cơ sở dữ liệu bằng cách truyền vào mã số sách của sách cần chỉnh sửa. Sau khi lấy được sách, chúng ta gán giá trị mới vào các thuộc tính của đối tượng sách này. Cuối cùng, chúng ta gọi phương thức SaveChanges của đối tượng db để lưu thay đổi vào cơ sở dữ liệu.
Đây là cách thức thực thi Code-first trong ASP.NET MVC thông qua lớp DbContext, giúp chúng ta tạo ra các lớp mô hình dữ liệu dễ dàng và linh hoạt hơn, cũng như thực hiện các thao tác với cơ sở dữ liệu một cách đơn giản và tiện lợi.
7. Khởi tạo Database với Test Data
Để khởi tạo cơ sở dữ liệu với dữ liệu thử nghiệm (test data) trong Entity Framework Code-first, chúng ta có thể sử dụng cơ chế Seed.
Cơ chế Seed được sử dụng để tạo dữ liệu mặc định hoặc dữ liệu thử nghiệm khi cơ sở dữ liệu được tạo ra. Để tạo cơ chế Seed, ta cần định nghĩa phương thức Seed() trong lớp kế thừa từ lớp System.Data.Entity.Migrations.SeedMigration.
Ví dụ:
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// configures one-to-many relationship
modelBuilder.Entity<Category>()
.HasMany(g => g.Products)
.WithRequired(s => s.Category)
.HasForeignKey(s => s.CategoryId);
}
public class MyInitializer : DropCreateDatabaseAlways<MyContext>
{
protected override void Seed(MyContext context)
{
// add categories
var categories = new List<Category>
{
new Category { Name = "Category 1" },
new Category { Name = "Category 2" },
new Category { Name = "Category 3" }
};
categories.ForEach(c => context.Categories.Add(c));
context.SaveChanges();
// add products
var products = new List<Product>
{
new Product { Name = "Product 1", CategoryId = 1 },
new Product { Name = "Product 2", CategoryId = 1 },
new Product { Name = "Product 3", CategoryId = 2 },
new Product { Name = "Product 4", CategoryId = 3 }
};
products.ForEach(p => context.Products.Add(p));
context.SaveChanges();
}
}
}
Trong đoạn mã trên, chúng ta định nghĩa lớp MyInitializer kế thừa từ DropCreateDatabaseAlways và định nghĩa phương thức Seed() để thêm các bản ghi mẫu vào cơ sở dữ liệu. Sau đó, ta có thể khởi tạo cơ sở dữ liệu và thêm dữ liệu mẫu bằng cách sử dụng đoạn mã sau:
Database.SetInitializer(new MyContext.MyInitializer());
var context = new MyContext();
context.Database.Initialize(true);
Ở đây, chúng ta sử dụng phương thức SetInitializer để thiết lập lớp khởi tạo cơ sở dữ liệu, sau đó sử dụng đối tượng MyContext để khởi tạo cơ sở dữ liệu và thêm dữ liệu mẫu bằng phương thức Initialize. Tham số truyền vào phương thức Initialize là true để bắt đầu quá trình khởi tạo cơ sở dữ liệu.
8. Truy vấn LINQ là gì
Truy vấn LINQ (Language Integrated Query) là một công nghệ trong .NET Framework cho phép lập trình viên truy vấn dữ liệu từ nhiều nguồn dữ liệu khác nhau (cơ sở dữ liệu, collection, XML document,...) bằng ngôn ngữ C# hoặc VB.NET, thay vì sử dụng SQL hay XPath.
LINQ cung cấp cho người lập trình cách tiếp cận trực quan hơn, linh hoạt hơn và ít lỗi hơn so với cách truy vấn truyền thống, đồng thời giúp tối ưu hóa hiệu suất ứng dụng bằng cách cho phép người lập trình đánh giá trước kết quả truy vấn. LINQ cũng giúp đơn giản hóa mã nguồn, nâng cao khả năng tái sử dụng và dễ dàng bảo trì mã nguồn.
8.1. Hướng dẫn Simple Linq
LINQ (Language-Integrated Query) là một công nghệ của .NET Framework cho phép truy vấn và xử lý dữ liệu từ nhiều nguồn khác nhau, bao gồm cả cơ sở dữ liệu, XML và các bộ sưu tập đối tượng.
Simple LINQ là một dạng truy vấn đơn giản trong LINQ, được sử dụng để lọc, sắp xếp và thực hiện các thao tác khác trên một bộ sưu tập đối tượng.
Dưới đây là hướng dẫn cách sử dụng Simple LINQ trong C#:
- Khai báo một bộ sưu tập đối tượng
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };
- Sử dụng toán tử "where" để lọc các phần tử thỏa mãn điều kiện
var filteredNumbers = from n in numbers
where n > 3
select n;
Hoặc có thể sử dụng phương thức mở rộng "Where" của lớp Enumerable
var filteredNumbers = numbers.Where(n => n > 3);
- Sử dụng toán tử "select" để chọn các thuộc tính của đối tượng
var filteredNames = from p in people
where p.Age > 18
select p.Name;
Hoặc có thể sử dụng phương thức mở rộng "Select" của lớp Enumerable
var filteredNames = people.Where(p => p.Age > 18).Select(p => p.Name);
- Sử dụng toán tử "orderBy" hoặc "orderByDescending" để sắp xếp các phần tử
var sortedNumbers = from n in numbers
orderby n descending
select n;
Hoặc có thể sử dụng phương thức mở rộng "OrderBy" hoặc "OrderByDescending" của lớp Enumerable
var sortedNumbers = numbers.OrderByDescending(n => n);
- Sử dụng toán tử "groupBy" để nhóm các phần tử theo thuộc tính
var groups = from p in people
group p by p.Age into g
select new { Age = g.Key, People = g };
Hoặc có thể sử dụng phương thức mở rộng "GroupBy" của lớp Enumerable
var groups = people.GroupBy(p => p.Age)
.Select(g => new { Age = g.Key, People = g });
Đây chỉ là những ví dụ đơn giản của Simple LINQ, LINQ còn có nhiều tính năng và toán tử khác để thao tác và xử lý dữ liệu.
8.2. Hướng dẫn Advanced Linq với Forming Projections, Filtering the data, Sorting the data, Grouping the data
LINQ là một công nghệ truy vấn dữ liệu mạnh mẽ và linh hoạt được tích hợp sẵn trong .NET Framework. LINQ cho phép chúng ta viết các truy vấn dữ liệu phức tạp bằng cách sử dụng các biểu thức LINQ, đồng thời cung cấp cú pháp dễ hiểu giống như SQL.
Bên dưới là hướng dẫn cơ bản về cách sử dụng LINQ trong .NET Framework:
Forming Projections
Projection trong LINQ là cách để chọn ra các thuộc tính hoặc giá trị từ các đối tượng trong một danh sách. Projection được sử dụng để trả về một danh sách mới với các thuộc tính được chọn.
Ví dụ: Lấy danh sách tên và địa chỉ của các khách hàng từ danh sách khách hàng.
var result = from c in customers
select new { Name = c.Name, Address = c.Address };
hoặc
var result = customers.Select(c => new { Name = c.Name, Address = c.Address });
Filtering the data
Filtering trong LINQ được sử dụng để lọc các bản ghi dựa trên các điều kiện.
Ví dụ: Lấy danh sách khách hàng có địa chỉ ở thành phố "Hanoi".
var result = from c in customers
where c.City == "Hanoi"
select c;
hoặc
var result = customers.Where(c => c.City == "Hanoi");
Sorting the data
Sorting trong LINQ được sử dụng để sắp xếp danh sách các đối tượng dựa trên các thuộc tính.
Ví dụ: Lấy danh sách khách hàng được sắp xếp theo tên theo thứ tự tăng dần.
var result = from c in customers
orderby c.Name ascending
select c;
hoặc
var result = customers.OrderBy(c => c.Name);
Grouping the data
Grouping trong LINQ được sử dụng để nhóm các đối tượng dựa trên các thuộc tính.
Ví dụ: Lấy danh sách khách hàng được nhóm theo thành phố.
var result = from c in customers
group c by c.City into g
select new { City = g.Key, Customers = g };
hoặc
var result = customers.GroupBy(c => c.City)
.Select(g => new { City = g.Key, Customers = g });
Đó là một số ví dụ về cách sử dụng LINQ trong .NET Framework. LINQ còn có rất nhiều tính năng mạnh mẽ khác như Join, Aggregate, Any, All, Distinct, Union, Intersect, Except, Skip, Take, First, Last, Single, ... Chúng ta có thể tìm hiểu thêm các tíng năng này trong tài liệu và sách học tập về LINQ hoặc trên các trang web chuyên về lập trình .NET. Bên cạnh đó, việc thực hành và áp dụng LINQ vào các dự án thực tế sẽ giúp chúng ta nắm vững và hiểu rõ hơn về cách sử dụng LINQ để xử lý dữ liệu trong ứng dụng .NET của mình.