本文章是根據 微軟MVP solenovex(楊旭)老師的視頻教程編寫而來,再加上自己的一些理解。
視頻教程地址:https://www.bilibili.com/video/BV1xa4y1v7rR
GitHub源碼:https://github.com/hllive/LearnEFCore3.1
Model之間的【多對多】【一對多】【 一對一】的關系怎么設定,或者說數據表之間的【多對多】【一對多】【 一對一】的關系怎么設定;
1、屬性特性
我們先講一下這些字段或者叫屬性,它們的屬性怎么設定,比如說這個name這個屬性,它在數據庫中的字段類型是NVARCHAR(MAX),而實際上它的長度應該有一定限制,比如要求長度不超過100,那可以使用DataAnnotations的attribute[Maxlength(100)]
使用DataAnnotations需要在Nuget中安裝System.ComponentModel.Annotations包

- 添加好attribute后說明Name字段最大長度為100
- 添加[Required]說明它是必填的
- Birth是出生日期,只需要年月日,在數據庫中卻是DATETIME2(7) ,這里就需要設置數據庫為日期類型

再執行遷移命令生成新的遷移文件
add-migration changePlayerColumb
生成成功后再執行
Update-Database
將數據庫更新為指定的遷移
其他更多特性請參考:https://www.cnblogs.com/dotnetmvc/p/3734272.html支持的完整特性列表
2、表之間關系
以下三個Model都是一對多的關系

Club可以看到有一個導航屬性League,導航到一個單個的League上面,所以說每個Club都對應一個League,而這個每個Club對應的League他有可能是同一個,所以說一個League就可能對應多個Club,這樣就體現了一對多的關系,只在Club一個類里體現就可以了
既然有了這種一對多的關系,那么在子表也就是Club表里或者是Club的Model里邊兒應該有一個字段是叫外鍵,實際上在類Club中沒有,在數據庫Club外鍵中是有LeagueId。在C#類中沒有寫LeagueId,EFCore會生成一個LeagueId外鍵,我們也可以在類中手動寫出來一個屬性,手動指定,也可以不寫,不寫的話EFCore會自動生成一個
Club和Player之間的一對多關系是怎么體現的呢,Club里的最后一個屬性也是這種導航屬性不過是另外一種形式的導航屬性,上面的League相當於是對單個的League,而對這個Player導航屬性的類型是一個集合,所以說呢?這相當於另外一個方向了,這個時候club是主表,然后Player是子表。

3、多對多關系
在三個Model的基礎上再建一個Model,叫比賽Game,就是每個隊員一個賽季可能要參加很多比賽,而每個比賽也有很多隊員同時去參加,所以說這個隊員和比賽之間就應該是多對多的關系(M:N),我們使用CFCore是無法直接實現多對多的關系
可以加一個中間表叫GamePlayer,比如說一個隊員他本賽季參加了五場比賽那么它就應該是對應的五個GamePlayer一對多的關系,它倆之間是一對多的關系1:M,每場比賽又有多個隊員去參加,每個隊員就相當於這場比賽的一個GamePlayer,所以說這個比賽和GamePlayer之間也是一對多的關系,這樣隊員和這個比賽之間就相當於間接地形成了一個這個多對多的關系。

創建一個Game類和GamePlayer類
public class Game
{
public Game()
{
GamePalyers = new List<GamePlayer>();
}
public Guid Id { get; set; }
public int Round { get; set; }//比賽階段
public DateTimeOffset? StartTime { get; set; }//開始時間
public List<GamePlayer> GamePalyers { get; set; }
}
public class GamePlayer
{
public Guid PlayerId { get; set; }
public Guid GameId { get; set; }
//這里也可以體現一對多的關系
public Game Game { get; set; }
public Player Player { get; set; }
}
在Player中添加一對多的關系

最后設定聯合主鍵,必須手動設定,在DbContext中設定,可以override OnModelCreating()

設定好后執行遷移命令
Add-Migration AddMage
執行更新數據庫
Update-Database

4、一對一的關系
假設每個隊員只能有一份簡歷,然后這一份簡歷呢,就屬於這一個隊員,所以這就屬於一對一的關系

創建一個Resume類
//簡歷
public class Resume
{
public Guid Id { get; set; }
[MaxLength(200)]
public string Description { get; set; }
public Guid PlayerId { get; set; }//Player外鍵
public Player Player { get; set; }//Player導航屬性
}
在Player類中添加簡歷屬性,這樣就能實現Resume和Player類的一對一關系

這時候EFCore會選擇其中一個類作為主表,但是EFCore可能會選錯,所以還是需要手動指定主外鍵
在DbContext中的OnModelCreating()方法中添加
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//設置聯合主鍵
modelBuilder.Entity<GamePlayer>().HasKey(x => new { x.PlayerId, x.GameId });
modelBuilder.Entity<Resume>()
.HasOne(x => x.Player)//一個Resume擁有一個Player
.WithOne(x => x.Resume)//每個Player又帶了一個Resume
.HasForeignKey<Resume>(x => x.PlayerId);//Resume上又帶了一個外鍵PlayerId
}
設定好后執行遷移命令<
Add-Migration AddResumeToOnePlayer
執行更新數據庫
Update-Database
如果執行遇到以下錯誤:請注意默認項目需要選擇Data項目

博客文章可以轉載,但不可以聲明為原創
