Entity Framework Core 3.1 入门(五)关联数据的添加和查询

此入门教程是记录下方参考资料视频的过程,本例基于Entity Framework Core 3.1
开发工具:Visual Studio 2019

参考资料:https://www.bilibili.com/video/BV1xa4y1v7rR

目录

Entity Framework Core 3.1 入门(一)创建项目

Entity Framework Core 3.1 入门(二)创建数据库和迁移(Migration)文件

Entity Framework Core 3.1 入门(三)一对一、多对多

Entity Framework Core 3.1 入门(四)增删改查

Entity Framework Core 3.1 入门(五)关联数据的添加和查询

Entity Framework Core 3.1 入门(六)一对一和多对多关系的增删改查

Entity Framework Core 3.1 入门(七)执行原生SQL语句

Entity Framework Core 3.1 入门(八)在 ASP.NET Core 中配置 Entity Framework Core

添加关系数据

调用DbContext的DbSet的Add()方法,然后保存即可,直接上代码

public static void Func_09()
{
      using var context = new DemoContext();

      var serieA = context.Leagues.Single(x => x.Name == "Serie A");

      var juventus = new Club
      {
          //设置导航属性,扯上关系
          League = serieA,
          Name = "Juventus",
          City = "Torino",
          DateOfEstablishment = new DateTime(1897, 11, 1),
          //设置导航属性,扯上关系
          Players = new List<Player>
          {
              new Player
              {
                  Name="C. Ronaldo",
                  DateOfBirth=new DateTime(1985,2,5)
              }
          }
      };

      context.Clubs.Add(juventus);

      var count = context.SaveChanges();
      Console.WriteLine("==============");
      Console.WriteLine(count);
}

也可以从导航属性设置,然后保存

public static void Func_10()
{
      using var context = new DemoContext();
      
      //先查询出需要执行添加操作的对象
      var juventus = context.Clubs.Single(x => x.Name == "Juventus");
      
      //使用Club的Players导航属性来添加数据
      //Add()方法添加关联数据,在对象的导航属性上直接添加即可
      juventus.Players.Add(new Player
      {
          Name = "Gonzalo Higuain",
          DateOfBirth = new DateTime(1987, 12, 10)
      });

      //保存更改
      var count = context.SaveChanges();
      Console.WriteLine("==============");
      Console.WriteLine(count);//2,Club表和Player表添加数据
}

实际应用,模拟前端传递数据到后端

public static void Func_11()
{
      using var context = new DemoContext();

      var juventus = context.Clubs.Single(x => x.Name == "Juventus");

      juventus.Players.Add(new Player
      {
          Name = "Matthijs de ligt",
          DateOfBirth = new DateTime(1999, 12, 18)
      });

      {
          //juventus相当于JSON传进来的,并且juventus中新添加的Player没主键
          using var newContext = new DemoContext();
          //添加追踪
          newContext.Clubs.Update(juventus);

          var count = newContext.SaveChanges();
          Console.WriteLine("==============");
          Console.WriteLine(count);//2,影响两行
          //因为两个表(Club和Player)都被设置为Modified
      }
}

上面的例子的Update()更改为Attach(),添加关系数据

public static void Func_12()
{
      using var context = new DemoContext();

      var juventus = context.Clubs.Single(x => x.Name == "Juventus");

      juventus.Players.Add(new Player
      {
          Name = "Miralem Pjanic",
          DateOfBirth = new DateTime(1990, 4, 2)
      });

      {
          //juventus相当于JSON传进来的,并且juventus中新添加的Player没主键
          using var newContext = new DemoContext();
          //添加追踪,将状态设置为UnChanged
          newContext.Clubs.Attach(juventus);

          var count = newContext.SaveChanges();
          Console.WriteLine("==============");
          Console.WriteLine(count);//1,影响一行
          //因为Club表未改变,状态也是UnChanged
          //因为新增的Player没主键,所以DbContext知道Player表有变化
      }
}

手动设置外键,添加关系数据

public static void Func_13()
{
      using var context = new DemoContext();

      var resume = new Resume
      {
          PlayerId = 1,//C. Ronaldo
          Description = "..."
      };

      context.Resumes.Add(resume);

      var count = context.SaveChanges();
      Console.WriteLine("==============");
      Console.WriteLine(count);//1
}

总结

查询关联数据

1.预加载,一次性把所有关联的数据预加载到DbContext

public static void Func_14()
{
      using var context = new DemoContext();
      //Include(),连同关联的属性对象一起查询出来
      //ThenInclude(),级联添加
      var clubs = context.Clubs
          .Where(x => x.Id > 0)
          .Include(x => x.League)
          .Include(x => x.Players)
              .ThenInclude(y => y.Resume)
          .Include(x => x.Players)
              .ThenInclude(y => y.GamePlayers)
                  .ThenInclude(z => z.Game)
          .ToList();

      //匿名类,显示需要的信息
      var info = context.Clubs
          .Where(x => x.Id > 0)
          .Select(x => new
          {
              x.Id,
              LeagueName = x.League.Name,
              x.Name,
              Player = x.Players
                  .Where(p =>
                      p.DateOfBirth > new DateTime(1990, 1, 1)),
          }).ToList();
      //DbContext 无法追踪匿名类,只能追踪它识别的类
      //但是此例中Player可以被追踪

      foreach (var data in info)
      {
          foreach (var player in data.Player)
          {
              player.Name += "~";
          }
      }

      context.SaveChanges();
}

显式加载

public static void Func_15()
{
      using var context = new DemoContext();

      //显式加载缺点:不能使用Club集合加载关联数据,只能使用单个数据
      var info = context.Clubs.First();
      //加载关联集合
      context.Entry(info)
          .Collection(x => x.Players)
          .Query()
          .Where(x => x.DateOfBirth > new DateTime(1990, 1, 1))
          .Load();

      //加载关联引用
      context.Entry(info)
          .Reference(x => x.League)
          .Load();
}

懒加载

EF Core默认关闭懒加载,这里就不演示了
懒加载也可以叫做按需加载、延迟加载。可以分两方面来理解,一方面指暂时不需要该数据,不用在当前马上加载,而可以推迟到使用它时再加载;另一方面指不确定是否将会需要该数据,所以暂时请不要加载,待确定需要后再加载它。懒加载是一种很重要的数据访问特性,可以有效地减少与数据源的交互(注意,这里所提的交互不是指交互次数,而是指交互的数据量),从而提升程序性能。

关联数据的添加和查询 结束

posted @ 2021-02-03 17:12  .NET好耶  阅读(157)  评论(0编辑  收藏  举报