Giới thiệu về các mối quan hệ trong Entity Framework Core

Cơ sở dữ liệu quan hệ là các kho lưu trữ dữ liệu có cấu trúc dựa trên cách các phần tử dữ liệu liên quan với nhau.

Lợi ích chính của việc xem dữ liệu theo quan hệ là giảm sự trùng lặp.

Ví dụ: bạn có thể muốn ghi lại dữ liệu về những người trong một thị trấn. Nếu bạn chọn cách tiếp cận không sử dụng dữ liệu quan hệ để ghi lại dữ liệu này, bạn sẽ lưu trữ tên của người đó cùng với địa chỉ, nơi làm việc, trường học, v.v. của họ dưới dạng các mục dữ liệu riêng lẻ.

Trường hợp nhiều người sống tại cùng một địa chỉ hoặc học cùng trường, bạn sẽ ghi lại địa chỉ hoặc chi tiết trường học ở nhiều nơi. Nếu tên trường đã từng thay đổi, bạn sẽ phải cập nhật nó trong mọi phần tử dữ liệu mà nó xuất hiện, đây là một công việc tốn thời gian và dễ xảy ra sai sót.

Trong cơ sở dữ liệu quan hệ, mỗi thực thể như người, trường học, nơi làm việc được lưu trữ trong các bảng riêng biệt và các thực thể được xác định bằng một giá trị khóa chính (primary key). Mối quan hệ hoặc liên kết giữa các thực thể được xác định trong cơ sở dữ liệu bởi sự tồn tại của khóa ngoại (foreign key).

Mối quan hệ Một - Nhiều trong Entity Framework Core

Sơ đồ sau mô tả mối quan hệ giữa các bảng Authors và Books trong cơ sở dữ liệu:

Mối quan hệ một - nhiều trong Entity Framework Core

Mỗi bảng có một khóa chính xác định sự duy nhất của một thực thể (hoặc hàng) trong bảng. Khóa chính của bảng Books là BookId và của bảng Authors là AuthorId. Cột AuthorId trong bảng Books là một khóa ngoại, giúp liên kết một cuốn sách để tác giả của nó.

Sách là thực thể phụ thuộc trong mối quan hệ. Tính toàn vẹn của nó phụ thuộc vào tham chiếu hợp lệ đến tác giả. Tác giả trở thành thực thể chính.

Sử dụng khóa ngoại, bạn có thể liên kết một bản ghi tác giả với nhiều bản ghi sách trong cơ sở dữ liệu. Loại mối quan hệ này được tìm thấy phổ biến nhất và được gọi là mối quan hệ Một - Nhiều.

Tùy thuộc vào phần mềm lập sơ đồ mà bạn sử dụng, bên một của mối quan hệ thường được mô tả bằng hình ảnh số 1 hoặc một chìa khóa. Bên nhiều của mối quan hệ thường được mô tả bằng dấu hoa thị (*) hoặc biểu tượng vô cực (∞). Số nhiều mô tả số lượng phần tử tiềm năng có thể được tìm thấy ở một đầu của mối quan hệ.

Thuộc tính điều hướng

Mối quan hệ giữa các thực thể trong một mô hình Entity Framework Core được xác định bởi Thuộc tính điều hướng (Navigation Properties). Thuộc tính điều hướng là thuộc tính mà trình cung cấp cơ sở dữ liệu sử dụng không thể ánh xạ tới kiểu nguyên thủy (hoặc kiểu vô hướng). Đoạn mã sau mô tả mô hình đại diện của ví dụ cơ sở dữ liệu ở trên:

public class Author
{
    public int AuthorId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<Book> Books { get; set; }
}

public class Book
{
    public int BookId { get; set; }
    public string Title { get; set; }
    public Author Author { get; set; }
}

Cả hai lớp chứa các thuộc tính mà kiểu dữ liệu có thể được ánh xạ tới các kiểu dữ liệu của cơ sở dữ liệu hiện có như int, string nhưng chúng cũng chứa các thuộc tính mà không thể được ánh xạ. Không có kiểu tương đương trong cơ sở dữ liệu cho kiểu Book hoặc kiểu Author. Do đó chúng được xem như thuộc tính điều hướng.

Định nghĩa của lớp Book cho phép mỗi cuốn sách có nhiều nhất một tác giả thông qua thuộc tính điều hướng Author (thuộc tính điều hướng tham chiếu) và định nghĩa của lớp Author cho phép mỗi tác giả có nhiều sách thông qua thuộc tính điều hướng Books (thuộc tính điều hướng tập hợp).

Kết hợp cùng nhau, chúng xác định mối quan hệ một - nhiều. Thực thể chính trong mối quan hệ một - nhiều là thực thể có thuộc tính điều hướng tập hợp và thực thể phụ thuộc là thực thể có thuộc tính điều hướng tham chiếu.

Thuộc tính điều hướng cho phép điều hướng liên kết giữa hai loại thông qua mã như sau:

book.Author = new Author();

foreach (var book in author.Books)
{
    //...
}

Tìm hiểu thêm về cách tạo, sửa đổi và xóa mối quan hệ một - nhiều trong Entity Framework Core ở bài viết sau:

Quản lý mối quan hệ Một - Nhiều trong Entity Framework Core
Trong hướng dẫn này, bạn sẽ tìm hiểu cách tạo, sửa đổi và xóa mối quan hệ một - nhiều trong Entity Framework Core.

Mối quan hệ Nhiều - Nhiều trong Entity Framework Core

Loại mối quan hệ phổ biến thứ hai được gọi là mối quan hệ Nhiều - Nhiều.

Mỗi cuốn sách có thể thuộc nhiều thể loại và mỗi thể loại có thể chứa nhiều cuốn sách.

Loại mối quan hệ này được quản lý trong cơ sở dữ liệu thông qua việc sử dụng một bảng nối (còn được gọi là bảng cầu nối hoặc bảng liên kết).

Loại mối quan hệ này được định nghĩa trong mã bằng cách thêm các thuộc tính tập hợp trong mỗi thực thể như sau:

public class Book
{
    public int BookId { get; set; }
    public string Title { get; set; }
    public Author Author { get; set; }
    public ICollection<Category> Categories { get; set; }
} 

public class Category
{
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
    public ICollection<Book> Books { get; set; }
}
Lưu ý: Mặc dù trong các phiên bản trước của Entity Framework, cách tiếp cận này đủ để Entity Framework tạo các bảng thích hợp và hình thành các mối quan hệ chính xác, tuy nhiên trong Entity Framework Core thì không. Cần phải thêm một thực thể trong mô hình để đại diện cho bảng nối.

Mối quan hệ một - một trong Entity Framework Core

Mối quan hệ Một - Một (hoặc thường là một đến không hoặc một) tồn tại khi chỉ có một hàng dữ liệu trong bảng chính được liên kết với 0 hoặc một hàng trong bảng phụ thuộc.

Sơ đồ sau minh họa mối quan hệ này giữa bảng Authors và bảng AuthorBiographies:

Mối quan hệ một - một trong Entity Framework Core

Ví dụ sau cho thấy mối quan hệ này được mô hình hóa như thế nào trong mã:

public class Author
{
    public int AuthorId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public AuthorBiography Biography { get; set; }
}

public class AuthorBiography
{
    public int AuthorBiographyId { get; set; }
    public string Biography { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string PlaceOfBirth { get; set; }
    public string Nationality { get; set; }
    public int AuthorId { get; set; }
    public Author Author { get; set; }
}

Trong ví dụ về mối quan hệ một - một này, mỗi Tác giả có thể có một và chỉ một thông tin tiểu sử tác giả.

Một lý do để thực hiện kiểu quan hệ này là khi bạn đang làm việc với kế thừa. Ví dụ: bạn có thể có một thực thể Xe cộ, với các lớp con như Ô tô, Xe tải, Xe máy, v.v.

Một lý do khác liên quan đến thiết kế cơ sở dữ liệu và / hoặc hiệu suất của cơ sở dữ liệu. Ví dụ: bạn có thể muốn áp dụng bảo mật cơ sở dữ liệu bổ sung cho bảng phụ thuộc vì nó chứa thông tin bí mật (ví dụ: hồ sơ sức khỏe của nhân viên) hoặc bạn chỉ muốn di chuyển dữ liệu không được tham chiếu thường xuyên vào một bảng riêng biệt để cải thiện thời gian tìm kiếm và truy xuất dữ liệu được sử dụng mọi lúc.

Tách bảng (table splitting)

Entity Framework Core (từ phiên bản 2.0) cũng hỗ trợ tách bảng, một kỹ thuật cho phép bạn sử dụng một bảng duy nhất để đại diện cho cả hai thực thể trong mối quan hệ một - một trong đó không cần tách thành nhiều bảng.

Sử dụng tính năng này, mối quan hệ một - một được minh họa ở trên sẽ được lưu trữ trong một bảng cơ sở dữ liệu cùng nhau:

Tách bảng (table splitting)

Mỗi thực thể cần được định nghĩa riêng biệt và chúng phải chia sẻ cùng một giá trị khóa chính. Loại mối quan hệ này yêu cầu cấu hình sẽ được trình bày chi tiết ở những bài viết tiếp theo.

Tùy chọn hành động ràng buộc tham chiếu

Để duy trì tính toàn vẹn tham chiếu của dữ liệu, bạn có thể chỉ định hành động mà cơ sở dữ liệu sẽ thực hiện trong trường hợp cố gắng xóa hoặc cập nhật khóa chính hiện đang được tham chiếu bởi khóa ngoại trong bảng khác.

Bạn có thể thực hiện việc này thông qua mệnh đề ON DELETE hoặc ON UPDATE khi  định nghĩa ràng buộc khóa ngoại.

Đây là sơ đồ hiển thị cơ sở dữ liệu đơn giản về sách và tác giả để giúp minh họa từng tùy chọn:

Tùy chọn hành động ràng buộc tham chiếu

Các tác giả được liên kết với sách thông qua khóa ngoại AuthorId trên bảng Books. Câu lệnh SQL để tạo ràng buộc khóa ngoại như sau:

CONSTRAINT [FK_Books_Authors_AuthorId] FOREIGN KEY ([AuthorId]) REFERENCES [Authors] ([AuthorId])

Các mệnh đề ON DELETE hoặc ON UPDATE thường được gắn vào câu lệnh này.

NO ACTION khi Xóa / Cập nhật

Đây là tùy chọn mặc định nếu ON DELETE hoặc ON UPDATE không được chỉ định. Nếu cố gắng xóa bản ghi Tác giả hiện được tham chiếu bởi bản ghi Sách, cơ sở dữ liệu sẽ phát sinh lỗi và quá trình xóa sẽ được khôi phục lại.

Điều tương tự cũng sẽ xảy ra nếu cố gắng thay đổi giá trị khóa chính của bản ghi Tác giả đang được sử dụng làm khóa ngoại trong bản ghi Sách.

RESTRICT khi Xóa / Cập nhật

Đối với phần lớn các hệ thống cơ sở dữ liệu quan hệ, RESTRICT tương đương với NO ACTION.

Trường hợp RESTRICT được thực hiện cụ thể bởi hệ thống cơ sở dữ liệu, sự khác biệt là RESTRICT dẫn đến ràng buộc được kiểm tra ngay khi bắt đầu xử lý thay vì ở cuối xử lý như NO ACTION.

Thiết lập Null khi Xóa / Cập nhật

Nếu bản ghi Tác giả hiện được tham chiếu trong một hoặc nhiều bản ghi Sách bị xóa, giá trị cột AuthorId trong bản ghi Sách bị ảnh hưởng sẽ được cập nhật thành NULL.

Điều tương tự sẽ xảy ra nếu giá trị khóa chính của bản ghi Tác giả bị thay đổi. Thao tác này sẽ chỉ thành công nếu cột AuthorId trong bảng Books cho phép null.

Lưu ý Hành vi này không được bật theo mặc định. Bạn có thể sử dụng Fluent API để cấu hình.

Cascade khi Xóa / Cập nhật

Theo tùy chọn này, khi một Tác giả bị xóa, thao tác này cũng sẽ chuyển sang các bảng phụ thuộc, kết quả là tất cả các sách liên quan tới tác giả sẽ bị xóa.

Khi bạn cập nhật giá trị khóa chính cho một tác giả, tất cả các bản ghi sách có chứa giá trị đó làm khóa ngoại sẽ được cập nhật thành giá trị khóa ngoài mới.

Thiết lập mặc định khi Xóa / Cập nhật

Khi bản ghi Tác giả bị xóa hoặc có giá trị khóa được sửa đổi, các giá trị khóa ngoại trong bảng Sách được liên kết với bản ghi Tác giả bị ảnh hưởng sẽ được thay đổi thành giá trị mặc định của chúng.

Các trường khóa ngoại trong các bảng bị ảnh hưởng phải có một giá trị mặc định được chỉ định hoặc cho phép null, trong trường hợp này NULL được coi là giá trị mặc định. Mọi giá trị mặc định không phải NULL phải liên quan đến khóa hiện có trong bảng chính.

Những điều cần nhớ về các mối quan hệ trong Entity Framework Core

  1. Entity Framework Core hỗ trợ 3 loại mối quan hệ trong cơ sở dữ liệu quan hệ là: một - nhiều, nhiều - nhiều, một - một.
  2. Mối quan hệ một - nhiều là phổ biến nhất, nó được cấu hình dễ dàng trong Entity Framework Core bằng cách sử dụng thuộc tính điều hướng hoặc cấu hình thông qua Fluent API.
  3. Mối quan hệ nhiều - nhiều được cấu hình bằng Fluent API trong Entity Framework Core.
  4. Mối quan hệ một - một được cấu hình trong Entity Framework Core bằng cách sử dụng thuộc tính điều hướng hoặc cấu hình thông qua Fluent API.
Entity Framework Core
Bài Viết Liên Quan:
Cấu hình trong Entity Framework Core
Trung Nguyen 03/04/2021
Cấu hình trong Entity Framework Core

Trong hướng dẫn này, bạn sẽ tìm hiểu cách cấu hình sử dụng attribute, Fluent API để ghi đè các quy ước mặc đình trong Entity Framework Core.

Các quy ước trong Entity Framework Core
Trung Nguyen 03/04/2021
Các quy ước trong Entity Framework Core

Bạn sẽ tìm hiểu các quy ước được tính hợp sẵn trong Entity Framework Core để tạo khóa chính, khóa ngoại, bảng, lược đồ, cột, kiểu dữ liệu, index ...

Quản lý mối quan hệ Một - Nhiều trong Entity Framework Core
Trung Nguyen 03/04/2021
Quản lý mối quan hệ Một - Nhiều trong Entity Framework Core

Trong hướng dẫn này, bạn sẽ tìm hiểu cách tạo, sửa đổi và xóa mối quan hệ một - nhiều trong Entity Framework Core.

DbSet trong Entity Framework Core
Trung Nguyen 02/04/2021
DbSet trong Entity Framework Core

Trong bài viết này, bạn sẽ tìm hiểu về DbSet trong Entity Framework Core. Cách sử dụng DbSet để thêm, sửa đổi và xóa thực thể trong Entity Framework Core.