天天看點

Entity Framework Core-約定

作者:opendotnet

EF Core預設約定規則基于領域類和DbContext類建立資料庫Schema,例如-表名稱,列名稱,表關系,主鍵&外鍵 這些都是基于契約建立的

1 EF Core約定例子

讓我們通過一個例子來了解一下約定,我們有一個項目包含了下面2個領域類,Employee和Department

public class Employee              {              public int Id { get; set; }              public int DepartmentId { get; set; }              public string Name { get; set; }              public string Designation { get; set; }              public Department Department { get; set; }              }              public class Department              {              public int Id { get; set; }              public string Name { get; set; }               public ICollection<Employee> Employee { get; set; }              }           

這個項目的DbContext如下:

public class CompanyContext : DbContext              {              public CompanyContext(DbContextOptions<CompanyContext> options) : base(options)              {              }              public DbSet<Employee> Employee { get; set; }              }           

運作EF Core migrations 資料庫将建立2張表-Employee 和Department,約定負責建立資料庫Schema,即表、列、關系等,讓我們逐一檢視它們

1.1 Table

EF Core 約定建立資料庫表,表名稱和DbContext中定義的DbSet<T>屬性名稱是相同的

我們僅僅有一個DbSet類型的屬性Employee,是以EF Core将在資料庫中建立一張和屬性Emlpoyee名稱相同的表,我們可以通過改變該表的名字通過改變屬性名稱

public DbSet<Employee> Employee { get; set; }           

這是非常簡單的,但是第二張表也會被建立,但是我們沒有定義DbSet,這是因為EF Core會查找Employee 類發現内部引用了Department類,是以會建立Department表

在Employee類内部引用了Department類,通過該屬性,EntityFrameworkCore找到Department模型實體,并在資料庫中為其建立一個表

public Department Department { get; set; }           

1.2 Column

EF Core會根據領域類定義的屬性類建立資料庫表中對應的列

列名稱和屬性名稱保持一緻,Employee類中有4個屬性(Id,DepartmentId,Name,Designation),是以使用了屬性的名稱建立表的列

類似的Department表中也建立了2列(Id,Name)

引用和集合屬性能夠在兩張表中建立關聯,我們稍後将看這塊内容

1.3 C# 資料類型VS SQL Server列類型

接下來我們考慮EF Core 中的資料類型是如何對應到資料庫表中的資料類型,如下展示了C#資料類型和SQL Server資料庫資料類型的映射關系:

C# 資料類型 SQL Server 資料類型
int int
string nvarchar(Max)
decimal decimal(18,2)
float real
bool bit
long bigint()
datetime datetime
short smallint

在我們這個例子中,基于這兩張表的映射規則如下:

// Department table               Id INT IDENTITY (1, 1) NOT               Name VARCHAR (50) NOT               // Employee table              Id INT IDENTITY (1, 1) NOT               DepartmentId INT NOT               Name VARCHAR (100) NOT               Designation VARCHAR (25) NOT            

1.4 able Column(可空列)

可空列是針對所有的引用資料類型,例如:string,able,float?

1.5 Not Column(非空列)

EF Core會為表的主鍵建立不可為空的列,像float,int,Datetime

1.6 Primary Key(主鍵)

EF Core 會根據是否有Id屬性(或者是否包含了id文本的屬性)來建立主鍵(大小寫不敏感)如果Employee類包含了如下任何一個屬性的名稱(id,ID,iD,Id,employeeid,EmployeeId,EMPLOYEEID,EmPLoyEEid等),EF Core 會為Employee表建立主鍵1.7 Foreign Key(外鍵)

領域類引用的每個導航屬性都會建立外鍵,在我們的案例中,Employee&Department領域類,Employee表将建立一個名字為DepartmentId的外鍵這兩個實體是一對多的關系,department能包含多個employee,反之亦然

2 表之間關系

SQL Server 資料庫表關系有3種類型:

一對多關系

一對一關系

多對多關系

讓我們看一下EF Core契約是如何處理這三種情況的

2.1 一對多關系

我們将學習在EF Core 兩個領域類如何送出一對多的關系,假如我們有兩張表Country & City,我們知道在一個國家中有多個城市,意味着我們可以在這兩張表中建立一個一對多的關系

我們添加2個類,分别是Country & City

public class Country              {              public int Id { get; set; }              public string Name { get; set; }              }              public class City              {              public int Id { get; set; }              public string Name { get; set; }              }           

在兩張表中建立一個多對一的關系,我們有如下4種方式:

契約 1:建立一個引用導航入屬性

在City類建立引用導航屬性指向Country類:

public class City              {              public int Id { get; set; }              public string Name { get; set; }              public Country Country { get; set; } //Reference Navigation Property              }              public class Country              {              public int Id { get; set; }              public string Name { get; set; }              }           

執行EF Core Migrations 将會在資料庫City和Country表之間産生一個一對多的關系,City表包含了可為空的CountryId外鍵

Entity Framework Core-約定

契約 2:建立一個集合導航屬性

通過添加一個集合導航屬性也可以建立一個一對多的關系

public class City              {              public int Id { get; set; }               public string Name { get; set; }               }              public class Country              {              public int Id { get; set; }               public string Name { get; set; }              public ICollection<City> Cities { get; set; } // Collection Navigation Property              }           

這種方式和契約1做相同的工作

契約 3: 建立兩個導航屬性

也可以在實體中建立兩個導航屬性,實作一對多的關系

public class City              {              public int Id { get; set; }              public string Name { get; set; }              public Country Country { get; set; } //Reference Navigation Property               }              public class Country              {              public int Id { get; set; }              public string Name { get; set; }               public ICollection<City> Cities { get; set; } // Collection Navigation Property              }           

上面代碼我們在City實體類中添加了引用的導航屬性,在Country類中添加了集合導航屬性契約 4:使用契約 3 + 外鍵屬性

在這種情況下我們使用契約3的方式并且同時添加外鍵CountryId 屬性在City實體中

public class City              {              public int Id { get; set; }              public string Name { get; set; }              public int CountryId { get; set; } //Foreign Key entity              public Country Country { get; set; } //Reference Navigation Property               }                  public class Country              {              public int Id { get; set; }              public string Name { get; set; }              public ICollection<City> Cities { get; set; } // Collection Navigation Property              }           

2.2 一對一關系

在EF Core實體類中建立一對一的關系是非常簡單的,我們隻需要在兩個實體類中添加引用的導航屬性

下面代碼中我們已經建立一對一關系在Country&City實體類中

public class City              {              public int Id { get; set; }              public string Name { get; set; }              public Country Country { get; set; } //Reference Navigation Property              }              public class Country              {              public int Id { get; set; }              public string Name { get; set; }              public City City { get; set; } //Reference Navigation Property              }           

2.3 多對多關系

在兩個實體類中建立多對多關系,分别在兩個實體類中建立兩個集合導航屬性

public class City              {              public int Id { get; set; }              public string Name { get; set; }              public ICollection<Country> Country { get; set; } //Collection Navigation Property              }              public class Country              {              public int Id { get; set; }              public string Name { get; set; }              public ICollection<City> City { get; set; } //Collection Navigation Property              }           

這個通過在資料庫中添加一張名為CityCountry的表來實作,這張表将包含City和Country表的外鍵,我們在會講到如何在EF Core中使用Fluent API中會講到

總結

在這節中學習EF Core預設的契約方式源代碼位址:https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/EntityFrameworkCore/EFCoreConventions

參考資料

https://learn.microsoft.com/en-us/ef/core/modeling/relationships/conventions

https://www.yogihosting.com/delete-records-entity-framework-core/

繼續閱讀