本文章是根據 微軟MVP solenovex(楊旭)老師的視頻教程撰寫而來,再加上自己的一些理解,
視頻教程地址:https://www.bilibili.com/video/BV1xa4y1v7rR
GitHub原始碼:https://github.com/hllive/LearnEFCore3.1
1、添加多個關系資料
在第3章第2節-表之間關系可以看出
一個聯賽擁有多個俱樂部,聯賽(League)和俱樂部(Club)是一對多關系,
一個俱樂部擁有多個隊員,俱樂部(Club)和隊員(Player)是一對多關系,
首先添加一個俱樂部,俱樂部應該是添加到一個現有的聯賽中,可以先查出來一個聯賽,然后在聯賽中添加一個俱樂部,
通過3個Model可以看出,聯賽(League)中體現不出聯賽與俱樂部之間的關系,而在俱樂部(Club)中有聯賽(League)的導航屬性,這樣就可以把一個Club中的League屬性設為已知的League,這樣就把club和league關聯起了,
舉個例子更清晰:現在有個聯賽叫《第一季度足球聯賽》,邀請全國所有地區的足球隊參加;看到邀請后,新成立一個俱樂部叫《新智聯足球隊》,成立俱樂部后需要隊員加入啊,這里就添加了兩個隊員(王建國和李剛)
[HttpPost("Club")]
public IActionResult SaveClub()
{
//1、通過邀請碼獲取一個聯賽,叫《第一季度足球聯賽》
League league = _dbContext.Leagues.SingleOrDefault(l => l.Id == new Guid("4227506d-05e4-47a2-b94f-08d8451d5dc00"));
//2、創建一個俱樂部
var club = new Club
{
//3、將獲取的聯賽添加到俱樂部中
League = league,//這樣League和Club就關聯上了
//4、設定其他屬性
Name = "新智聯足球隊",
City = "貴州省貴陽市",
DateOfEstablishment = new DateTime(2020, 8, 23),
History = "參加很多比賽",
//5、添加隊員
Players=new List<Player>() {
new Player{ Name="王建國",Birth=new DateTime(1994,8,2) },
new Player{ Name="李剛",Birth=new DateTime(1994,9,25) }
}
};
//添加和保存
_dbContext.Clubs.Add(club);
int count = _dbContext.SaveChanges();
return Ok(count);
}
通過dbContext中DbSet的Add()方法把新成立的俱樂部添加到Context中,這樣Context就知道已經新添加了一個Club,然后呼叫SaveChange()方法就會執行資料庫的Insert陳述句

最終這個例子需要了解League和Club怎么關聯,Playe和Club怎么關聯
再查看一個例子
[HttpPost("GamePlayer")]
public IActionResult GamePlayer()
{
//1、查詢符合添加的隊員
var players = _dbContext.Players.Where(p => p.Birth > new DateTime(1995, 1, 1)).ToList();
//2、創建比賽物件
var game = new Game {
Round = 2,
StartTime = new DateTime(2020, 5, 1),
//3、將查詢出來的隊員集合與比賽建立關系
GamePalyers = players.Select(p => new GamePlayer { Player = p }).ToList()
};
//添加和保存
_dbContext.Games.Add(game);
int count = _dbContext.SaveChanges();
return Ok(count);
}
2、添加單個關系資料
再看一個例子:現在俱樂部成立后才兩個隊員,需要再添加隊員;那么添加單個隊員怎么添加呢?請看代碼
先從資料庫中把俱樂部查出來,由于俱樂部里有一個Players集合屬性導航,可以通過這個Players中的Add()方法來添加新的隊員,而俱樂部被contact變化追蹤的,所以添加一個新的隊員,context就知道這個隊員是新加的,并且不用設定外鍵,然后呢,我們SaveChange就可以了,因為context會把這些變化都了解到,然后計算出來應該執行哪些sql陳述句,
[HttpPost("Palyer")]
public IActionResult AddPalyer() {
//1、查詢出俱樂部
var club = _dbContext.Clubs.SingleOrDefault(l => l.Name == "新智聯足球隊");
//2、在俱樂部中添加隊員
club.Players.Add(new Player() { Name = "張全蛋", Birth = new DateTime(1999, 12, 1) });
//3、保存資料
int count = _dbContext.SaveChanges();
return Ok(count);
}
3、Attach的使用
首先通過一個例子可以看出,《1、查詢出俱樂部(不追蹤)》就相當于是離線資料,不被context追蹤,使用離線資料需要使用Update方法;在使用Update的時候Context發現在俱樂部中新添加了一個隊員,
[HttpPost("UseAttach")]
public IActionResult UseAttach()
{
//1、查詢出俱樂部(不追蹤)
var club = _dbContext.Clubs.AsNoTracking().SingleOrDefault(x => x.Name == "新智聯足球隊");
//2、在查詢出來的俱樂部中添加新隊員
club.Players.Add(new Player { Name = "陳浩杰", Birth = new DateTime(2000, 5, 6) });
//3、使用Update更新資料
_dbContext.Clubs.Update(club);//離線資料需要使用Update方法
//4、保存資料
int count = _dbContext.SaveChanges();
return Ok(count);
}

使用SaveChange()執行的SQL陳述句里包括查詢Club、更新Club和添加Player的操作,使用Update()方法會把俱樂部所有屬性值重新更新一下;
我們只是想添加一個新隊員,但是把俱樂部(Club)所有的屬性都更新了一遍,這種情況怎么辦呢?
使用Attach附加方法,在Club上附加物件,這時候Club是未修改狀態,context不會進行修改操作,但是發現在Player導航屬性中新添加了一個隊員,context會對新添加的隊員生成SQL陳述句;說明在Club上附加了一個新隊員,所以生成SQL陳述句的時候只插入了隊員的資料,Club和Player之間的關系也會自動生成
在上面的例子中,只需要把Update()方法修改為Attach()方法即可
[HttpPost("UseAttach")]
public IActionResult UseAttach()
{
//1、查詢出俱樂部(不追蹤)
var club = _dbContext.Clubs.AsNoTracking().SingleOrDefault(x => x.Name == "新智聯足球隊");
//2、在查詢出來的俱樂部中添加新隊員
club.Players.Add(new Player { Name = "陳浩杰", Birth = new DateTime(2000, 5, 6) });
//3、使用Update更新資料
//_dbContext.Clubs.Update(club);//離線資料需要使用Update方法
_dbContext.Clubs.Attach(club);//附加物件
//4、保存資料
int count = _dbContext.SaveChanges();
return Ok(count);
}

最后來看三個方法呼叫效果

博客文章可以轉載,但不可以宣告為原創
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/73.html
