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.
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>
.
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.
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.
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ể Student
và Grade
), 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.
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ể Student
và Grade
.
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ể Student
và Grade
sẽ trông giống như hình bên dưới, trong đó bảng Students
có khóa ngoại GradeId
.
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 Students
và Grades
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
.
Lưu ý: Thuộc tính tham chiếuGrade
là nullable, do đó nó tạo ra khóa ngoạiGradeId
Null trong bảngStudents
. 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 Students
và Grades
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.
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ể Student
và StudentAddress
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 Students
và StudentAddresses
trong cơ sở dữ liệu, như được hiển thị trong hình bên dưới.
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.
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