EF Core - Các quy ước trong Entity Framework Core

Các quy ước trong Entity Framework Core

Các quy ước là các quy tắc mặc định bằng cách sử dụng Entity Framework để xây dựng một mô hình dựa trên các lớp thực thể của bạn.

Trong bài viết Ứng dụng EF Core đầu tiên, EF Core API tạo ra một lược đồ cơ sở dữ liệu dựa trên các lớp thực thể và lớp Context, không có bất kỳ cấu hình bổ sung nào vì các lớp thực thể đã tuân theo các quy ước.

Hãy xem các lớp thực thể và lớp Context sau để hiểu các quy ước mặc định.


public class Student
{
    public int StudentId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public byte[] Photo { get; set; }
    public decimal Height { get; set; }
    public float Weight { get; set; }

    public int GradeId { get; set; }
    public Grade Grade { get; set; }
}

public class Grade
{
    public int Id { get; set; }
    public string GradeName { get; set; }
    public string Section { get; set; }

    public IList<Student> Students { get; set; }
}

public class SchoolContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    { 
        optionsBuilder.UseSqlServer(@"Server=.\SQLEXPRESS;Database=SchoolDB;Trusted_Connection=True;");
    }

    public DbSet<Student> Students { get; set; }
}

Chúng ta sẽ tìm hiểu các quy ước của EF Core và cách thức EF Core API tạo cơ sở dữ liệu cho các thực thể trên.

Lược đồ

Theo mặc định, EF Core sẽ tạo tất cả các đối tượng cơ sở dữ liệu trong lược đồ dbo.

Quy ước về lược đồ trong Entity Framework Core

Bảng

EF Core sẽ tạo các bảng cơ sở dữ liệu cho tất cả các thuộc tính DbSet<TEntity> trong lớp Context có cùng tên với thuộc tính.

Nó cũng sẽ tạo các bảng cho các thực thể không phải là thuộc tính DbSet nhưng có thể truy cập thông qua các thuộc tính tham chiếu trong các thực thể DbSet khác.

Đối với ví dụ trên, EF Core sẽ tạo bảng Students cho thuộc tính DbSet<Student> trong lớp SchoolContext và bảng Grade cho thuộc tính Grade trong lớp thực thể Student, mặc dù lớp SchoolContext không có thuộc tính DbSet<Grade>.

Quy ước về bảng trong Entity Framework Core

Cột

Theo mặc định, EF Core sẽ tạo các cột cho tất cả các thuộc tính của một lớp thực thể có cùng tên với thuộc tính.

Nó sử dụng các thuộc tính tham chiếu và thuộc tính tập hợp trong việc xây dựng mối quan hệ giữa các bảng tương ứng trong cơ sở dữ liệu.

Quy ước về cột trong Entity Framework Core

Kiểu dữ liệu cột

Kiểu dữ liệu cho các cột trong bảng cơ sở dữ liệu tùy thuộc vào cách nhà cung cấp cơ sở dữ liệu ánh xạ kiểu dữ liệu C# với kiểu dữ liệu của cơ sở dữ liệu đã chọn.

Bảng sau liệt kê ánh xạ giữa kiểu dữ liệu C# sang kiểu dữ liệu cột SQL Server.

Kiểu dữ liệu C# Ánh xạ tới kiểu dữ liệu SQL Server
int int
string nvarchar(Max)
decimal decimal(18,2)
float real
byte[] varbinary(Max)
datetime datetime
bool bit
byte tinyint
short smallint
long bigint
double float
char Không có ánh xạ
sbyte Không có ánh xạ (ném ra exception)
object Không có ánh xạ

Cột Null

EF Core tạo các cột null cho tất cả các kiểu dữ liệu tham chiếu và các thuộc tính kiểu nguyên thủy nullable, ví dụ: string, Nullable<int>, decimal?.

Cột NotNull

EF Core tạo các cột NotNull trong cơ sở dữ liệu cho tất cả các thuộc tính khóa chính và các thuộc tính kiểu nguyên thủy, ví dụ: int, float, decimal, DateTime, v.v.

Khóa chính

EF Core sẽ tạo cột khóa chính cho thuộc tính có tên Id hoặc <Entity Class Name>Id (không phân biệt chữ hoa chữ thường).

Ví dụ, EF Core sẽ tạo một cột khóa chính trong bảng Students nếu lớp Student có một thuộc tính có tên id, ID, iD, Id, studentid, StudentId, STUDENTID hoặc sTUdentID.

Quy ước về khóa chính trong Entity Framework Core

Khóa ngoại

Theo quy ước khóa ngoại, EF Core API sẽ tạo một cột khóa ngoại cho mỗi thuộc tính điều hướng tham chiếu trong một thực thể với một trong các mẫu đặt tên sau.

  • <Reference Navigation Property Name>Id
  • <Reference Navigation Property Name><Principal Primary Key Property Name>

Trong ví dụ của chúng tôi (các thực thể StudentGrade), EF Core sẽ tạo một cột khóa ngoại GradeId trong bảng Students, như được mô tả trong hình dưới đây.

Quy ước về khóa ngoại trong Entity Framework Core

Bảng sau liệt kê các tên cột khóa ngoại cho các tên thuộc tính tham chiếu khác và các tên thuộc tính khóa chính.

Tên thuộc tính tham chiếu trong thực thể phụ thuộc Tên thuộc tính khóa ngoại trong thực thể phụ thuộc Tên thuộc tính khóa chính Tên cột khóa ngoại trong DB
Grade GradeId GradeId GradeId
Grade - GradeId GradeId
Grade - Id GradeId
CurrentGrade CurrentGradeId GradeId CurrentGradeId
CurrentGrade - GradeId CurrentGradeGradeId
CurrentGrade - Id CurrentGradeId
CurrentGrade GradeId Id GradeId

Index

Theo mặc định, EF Core tạo clustered index trên các cột khóa chính và non-clustered index trên các cột khóa ngoại.

Quy ước về mối quan hệ một-nhiều trong EF Core

Ở phần này, bạn sẽ tìm hiểu về các quy ước mối quan hệ giữa hai lớp thực thể dẫn đến mối quan hệ một-nhiều giữa các bảng tương ứng trong cơ sở dữ liệu.

Entity Framework Core tuân theo quy ước tương tự như các quy ước mối quan hệ một-nhiều trong Entity Framework 6.x. Sự khác biệt duy nhất là EF Core tạo cột khóa ngoại có cùng tên với tên thuộc tính điều hướng chứ không phải là <NavigationPropertyName>_<PrimaryKeyPropertyName> như trong Entity Framework.

Chúng ta sẽ xem các quy ước khác nhau trong EF Core tự động cấu hình mối quan hệ một-nhiều giữa các thực thể StudentGrade.


public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }
}
       
public class Grade
{
    public int GradeId { get; set; }
    public string GradeName { get; set; }
    public string Section { get; set; }
}

Sau khi áp dụng các quy ước cho mối quan hệ một-nhiều trong các thực thể ở trên, các bảng cơ sở dữ liệu cho các thực thể StudentGrade sẽ trông giống như hình bên dưới, trong đó bảng Students có khóa ngoại GradeId.

Quy ước về quan hệ một nhiều trong Entity Framework Core

Quy ước 1

Chúng tôi muốn thiết lập mối quan hệ một-nhiều trong đó nhiều học sinh được liên kết với một lớp.

Điều này có thể đạt được bằng cách thêm một thuộc tính điều hướng tham chiếu trong thực thể phụ thuộc như dưới đây. (ở đây, thực thể Student là thực thể phụ thuộc và thực thể Grade là thực thể chính).


public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
   
    public Grade Grade { get; set; }
}

public class Grade
{
    public int GradeId { get; set; }
    public string GradeName { get; set; }
    public string Section { get; set; }
}

Trong ví dụ trên, lớp thực thể Student có một thuộc tính điều hướng tham chiếu kiểu Grade. Điều này cho phép chúng ta liên kết một thực thể Grade với nhiều thực thể Student khác.

Điều này sẽ tạo ra mối quan hệ một-nhiều giữa các bảng StudentsGrades trong cơ sở dữ liệu, trong đó bảng Students có khóa ngoại GradeId Null, như được hiển thị trong hình bên dưới.

EF Core sẽ tạo một thuộc tính ẩn (shadow property) cho khóa ngoại có tên GradeId trong mô hình khái niệm, sẽ được ánh xạ tới cột khóa ngoại GradeId trong bảng Students.

Quy ước về quan hệ một nhiều trong Entity Framework Core

Lưu ý: Thuộc tính tham chiếu Grade là nullable, do đó nó tạo ra khóa ngoại GradeId Null trong bảng Students. Bạn có thể cấu hình các khóa ngoại NotNull bằng Fluent API.

Quy ước 2

Một quy ước khác là thêm một thuộc tính điều hướng tập hợp trong thực thể chính như dưới đây.


public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }
}

public class Grade
{
    public int GradeId { get; set; }
    public string GradeName { get; set; }
    public string Section { get; set; }

    public ICollection<Student> Students { get; set; } 
}

Trong ví dụ trên, thực thể Grade có một thuộc tính điều hướng tập hợp kiểu ICollection<student>.

Điều này sẽ cho phép chúng ta thêm nhiều thực thể Student vào một thực thể Grade, mà kết quả là mối quan hệ một-nhiều giữa bảng Students và bảng Grades trong cơ sở dữ liệu, tương tự như trong quy ước 1.

Quy ước 3

Một quy ước khác của EF Core cho mối quan hệ một-nhiều là có thuộc tính điều hướng ở cả hai đầu của mối quan hệ, điều này cũng sẽ dẫn đến mối quan hệ một-nhiều (quy ước 1 + quy ước 2).


public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    public Grade Grade { get; set; }
}

public class Grade
{
    public int GradeID { get; set; }
    public string GradeName { get; set; }
    
    public ICollection<Student> Students { get; set; }
}

Trong ví dụ trên, lớp thực thể Student có thuộc tính điều hướng tham chiếu kiểu Grade và lớp thực thể Grade có thuộc tính điều hướng tập hợp kiểu ICollection<Student> dẫn đến mối quan hệ một-nhiều giữa các bảng StudentsGrades trong cơ sở dữ liệu, giống như trong quy ước 1.

Quy ước 4

Chỉ định đầy đủ mối quan hệ ở cả hai đầu với thuộc tính khóa ngoại trong thực thể phụ thuộc tạo ra mối quan hệ một-nhiều.


public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int GradeId { get; set; }
    public Grade Grade { get; set; }
}

public class Grade
{
    public int GradeId { get; set; }
    public string GradeName { get; set; }

    public ICollection<Student> Students { get; set; }
}

Trong ví dụ trên, thực thể Student có một thuộc tính khóa ngoại GradeId có kiểu int và thuộc tính điều hướng tham chiếu của nó là Grade.

Ở đầu kia, thực thể Grade cũng có một thuộc tính điều hướng tập hợp kiểu ICollection<Student>. Điều này sẽ tạo mối quan hệ một-nhiều với cột khóa ngoại NotNull trong bảng Students, như được hiển thị trong hình bên dưới.

Quy ước về quan hệ một nhiều trong Entity Framework Core

Nếu bạn muốn tạo khóa ngoại GradeId thành Null, thì hãy sử dụng kiểu dữ liệu int nullable (Nullable<int> hoặc int?), như ví dụ bên dưới.


public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int? GradeId { get; set; } 
    public Grade Grade { get; set; }
}

Như vậy là chúng ta đã tìm hiểu về các quy ước tự động tạo mối quan hệ một-nhiều trong các bảng cơ sở dữ liệu tương ứng. Nếu các thực thể không tuân theo các quy ước trên, thì bạn có thể sử dụng Fluent API để cấu hình mối quan hệ một-nhiều.

Quy ước về mối quan hệ một-một trong EF Core

Entity Framework Core đã giới thiệu các quy ước mặc định tự động định cấu hình mối quan hệ một-một giữa hai thực thể (EF 6.x hoặc trước đó không hỗ trợ các quy ước cho mối quan hệ một-một).

Trong EF Core, mối quan hệ một-một đòi hỏi một thuộc tính điều hướng tham chiếu ở cả hai bên. Sau đây các thực thể StudentStudentAddress tuân theo quy ước cho mối quan hệ một-một.


public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
       
    public StudentAddress Address { get; set; }
}

public class StudentAddress
{
    public int StudentAddressId { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public int StudentId { get; set; }
    public Student Student { get; set; }
}

Trong ví dụ trên, thực thể Student có một thuộc tính điều hướng tham chiếu thuộc kiểu StudentAddress và thực thể StudentAddress có một thuộc tính khóa ngoại StudentId và thuộc tính tham chiếu tương ứng của nó là Student.

Điều này sẽ dẫn đến mối quan hệ một-một trong các bảng tương ứng StudentsStudentAddresses trong cơ sở dữ liệu, như được hiển thị trong hình bên dưới.

Quy ước về mối quan hệ một-một trong EF Core

EF Core tạo một unique index trên cột khóa ngoại StudentId NotNull trong bảng StudentAddresses, như được hiển thị ở trên.

Điều này đảm bảo rằng giá trị của cột khóa ngoại StudentId phải là duy nhất trong bảng StudentAddress, điều cần thiết cho mối quan hệ một-một.

Lưu ý: Ràng buộc duy nhất được hỗ trợ trong Entity Framework Core nhưng không phải trong EF 6 và đó là lý do tại sao EF Core có các quy ước cho mối quan hệ một-một còn EF 6.x thì không có.

Ngoài ra bạn cũng có thể sử dụng Fluent API để cấu hình mối quan hệ một-một nếu các thực thể không tuân theo các quy ước