EFCore-实体跟踪

EFCore-实体跟踪

EFCore实现了直接对实体类对象进行操作可以直接影响表中数据

将实体类和数据表绑定的更加紧密了


实体跟踪

在实体类和数据表建立关系那一刻,EFCore就会将该实体标记并且跟踪实体类

在DbContext中注册的DbSet在调用时有五种状态

  • 已添加(Added):DbContext正在跟踪此实体,但数据库中还没存在
  • 未改变(Unchanged):DbContext正在跟踪此实体,该实体存在于数据库中,其属性值和从数据库中得到的值一致,未发生改变
  • 已修改(Modified):DbContext正在跟踪此实体,并存在与数据库中,并且其部分或全部属性值已修改
  • 已删除(Deleted):DbContext正在跟踪此实体,并存在与数据库中,但下次调用SaveChanges时要从数据库中删除对应数据
  • 已分离(Detached):DbContext未跟踪该实体

在SaveChanges()的时候,根据实体状态的不同,生成Update、Delete、Insert等SQL语句,来将内存中实体的变化推送到数据库中


AsNoTracking

基于这种跟踪机制,微软会使用内存来持续跟踪,这无疑是占用了一部分内存的

我们可以手动让其不跟踪实体,在进行查询的时候,这种方式是一种对资源不错的优化

但要进行增删改操作,就不能让其不跟踪,否则实体类修改后表中数据不会改变


批量的增删改

模型驱动的EFCore的LINQ语法更适合去进行数据库查询,而面对批量增删改的时候并不是很好用

但EFCore7.0版本之后已经增加了高效批量操作的方法:

  • ExecuteUpdateAsync
  • ExecuteDeleteAsync

需要注意的是,执行这两个方法的时候,EFCore是不会对实体进行状态跟踪的

杨中科提供了一个自己写的框架,可以用EFCore对数据进行批量操作

导入依赖

Zack.EFCore.Batch.Npgsql_NET6


软删除

在之前的Java项目中,已经接触过很多次软删除的概念了

在EFCore中,我们可以通过全局查询筛选器来添加一个查询条件

在每次查询的时候,都将这个查询条件加在SQL中,就能筛选掉“被删除”的数据库

public class DBContext : DbContext
{
    public DbSet<Article> Articles { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Article>(entity =>
        {
            entity.ToTable("Articles");
            // 配置全局查询过滤器,将Is_Deleted == 0 作为查询条件
            entity.HasQueryFilter(a => a.Is_Deleted == 0);
        });
    }
}

查看已删除的数据

调用IgnoreQueryFilters忽略掉全局过滤器,在手动添加条件为Is_Deleted == 0的查询条件

using (var dbContext = new DBContext())
{
    dbContext.Articles.IgnoreQueryFilters().Where(a => a.Is_Deleted == 1);
}