本文章是根据 微软MVP solenovex(杨旭)老师的视频教程编写而来,再加上本身的一些理解。
视频教程地址:https://www.bilibili.com/video/BV1xa4y1v7rR
GitHub源码:https://github.com/hllive/LearnEFCore3.1html
在第3章第2节-表之间关系能够看出
一个联赛拥有多个俱乐部,联赛(League)和俱乐部(Club)是一对多关系,
一个俱乐部拥有多个队员,俱乐部(Club)和队员(Player)是一对多关系。
首先添加一个俱乐部,俱乐部应该是添加到一个现有的联赛中。能够先查出来一个联赛,而后在联赛中添加一个俱乐部。
经过3个Model能够看出,联赛(League)中体现不出联赛与俱乐部之间的关系,而在俱乐部(Club)中有联赛(League)的导航属性,这样就能够把一个Club中的League属性设为已知的League,这样就把club和league关联起了。git
举个例子更清晰:如今有个联赛叫《第一季度足球联赛》,邀请全国全部地区的足球队参加;看到邀请后,新成立一个俱乐部叫《新智联足球队》,成立俱乐部后须要队员加入啊,这里就添加了两个队员(王建国和李刚)github
[HttpPost("Club")] public IActionResult SaveClub() { //一、经过邀请码获取一个联赛,叫《第一季度足球联赛》 League league = _dbContext.Leagues.SingleOrDefault(l => l.Id == new Guid("4227506d-05e4-47a2-b94f-08d8451d5dc00")); //二、建立一个俱乐部 var club = new Club { //三、将获取的联赛添加到俱乐部中 League = league,//这样League和Club就关联上了 //四、设置其余属性 Name = "新智联足球队", City = "贵州省贵阳市", DateOfEstablishment = new DateTime(2020, 8, 23), History = "参加不少比赛", //五、添加队员 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怎么关联sql
再查看一个例子数据库
[HttpPost("GamePlayer")] public IActionResult GamePlayer() { //一、查询符合添加的队员 var players = _dbContext.Players.Where(p => p.Birth > new DateTime(1995, 1, 1)).ToList(); //二、建立比赛对象 var game = new Game { Round = 2, StartTime = new DateTime(2020, 5, 1), //三、将查询出来的队员集合与比赛创建关系 GamePalyers = players.Select(p => new GamePlayer { Player = p }).ToList() }; //添加和保存 _dbContext.Games.Add(game); int count = _dbContext.SaveChanges(); return Ok(count); }
再看一个例子:如今俱乐部成立后才两个队员,须要再添加队员;那么添加单个队员怎么添加呢?请看代码ide
先从数据库中把俱乐部查出来,因为俱乐部里有一个Players集合属性导航,能够经过这个Players中的Add()方法来添加新的队员。而俱乐部被contact变化追踪的,因此添加一个新的队员,context就知道这个队员是新加的。而且不用设定外键,而后呢,咱们SaveChange就能够了,由于context会把这些变化都了解到,而后计算出来应该执行哪些sql语句。ui
[HttpPost("Palyer")] public IActionResult AddPalyer() { //一、查询出俱乐部 var club = _dbContext.Clubs.SingleOrDefault(l => l.Name == "新智联足球队"); //二、在俱乐部中添加队员 club.Players.Add(new Player() { Name = "张全蛋", Birth = new DateTime(1999, 12, 1) }); //三、保存数据 int count = _dbContext.SaveChanges(); return Ok(count); }
首先经过一个例子能够看出,《一、查询出俱乐部(不追踪)》就至关因而离线数据,不被context追踪,使用离线数据须要使用Update方法;在使用Update的时候Context发如今俱乐部中新添加了一个队员。3d
[HttpPost("UseAttach")] public IActionResult UseAttach() { //一、查询出俱乐部(不追踪) var club = _dbContext.Clubs.AsNoTracking().SingleOrDefault(x => x.Name == "新智联足球队"); //二、在查询出来的俱乐部中添加新队员 club.Players.Add(new Player { Name = "陈浩杰", Birth = new DateTime(2000, 5, 6) }); //三、使用Update更新数据 _dbContext.Clubs.Update(club);//离线数据须要使用Update方法 //四、保存数据 int count = _dbContext.SaveChanges(); return Ok(count); }
使用SaveChange()执行的SQL语句里包括查询Club、更新Club和添加Player的操做,使用Update()方法会把俱乐部全部属性值从新更新一下;
咱们只是想添加一个新队员,可是把俱乐部(Club)全部的属性都更新了一遍。这种状况怎么办呢?code
使用Attach附加方法,在Club上附加对象,这时候Club是未修改状态,context不会进行修改操做,可是发如今Player导航属性中新添加了一个队员,context会对新添加的队员生成SQL语句;说明在Club上附加了一个新队员,因此生成SQL语句的时候只插入了队员的数据,Club和Player之间的关系也会自动生成视频
在上面的例子中,只须要把Update()方法修改成Attach()方法便可
[HttpPost("UseAttach")] public IActionResult UseAttach() { //一、查询出俱乐部(不追踪) var club = _dbContext.Clubs.AsNoTracking().SingleOrDefault(x => x.Name == "新智联足球队"); //二、在查询出来的俱乐部中添加新队员 club.Players.Add(new Player { Name = "陈浩杰", Birth = new DateTime(2000, 5, 6) }); //三、使用Update更新数据 //_dbContext.Clubs.Update(club);//离线数据须要使用Update方法 _dbContext.Clubs.Attach(club);//附加对象 //四、保存数据 int count = _dbContext.SaveChanges(); return Ok(count); }
博客文章能够转载,但不能够声明为原创