EF Core 实体数据监测机制

文章目录

  • 前言
  • 一、变更跟踪的核心机制
  • 二、ChangeTracker 的作用
    • 1)DbContext 中的 ChangeTracker 组件负责管理所有被跟踪实体的状态。关键功能包括:
    • 2)查看不同操作下实体状态(增、删、改等)
  • 三、 显示状态控制
    • 1)手动设置状态
    • 2)部分更新:若仅需更新特定字段,可标记修改的属性
  • 四、性能优化策略
    • 1)无跟踪查询(如果查询出来的对象不会被修改、删除等):使用 AsNoTracking 避免不必要的跟踪,提升查询性能
    • 2)批量操作:通过 AddRange、UpdateRange 等方法减少变更检测开销
    • 3)关闭自动检测:在密集更新场景中,暂时禁用自动检测
  • 五、并发控制
    • 1)EF Core 使用 乐观并发控制 处理并发冲突
  • 六、变更跟踪代理(高级)
    • EF Core 支持通过 变更跟踪代理 实现即时变更通知(需满足特定条件,如属性为 virtual):
  • 总结


前言

Entity Framework Core (EF Core) 通过以下机制检测实体数据的变化,确保在调用 SaveChanges 时能够准确同步到数据库


一、变更跟踪的核心机制

EF Core 默认使用 快照跟踪(Snapshot Tracking) 来监控实体状态变化。具体流程如下:

  1. 快照创建:当实体首次被加载到 DbContext(如通过查询或附加操作)时,EF Core 会为该实体的每个属性记录初始值的快照。
  2. 值比较:每次访问实体属性时,EF Core 会将当前值与快照值进行比对。
  3. 状态标记:若检测到值的变化,该实体的状态会被标记为 Modified,相关属性被标记为已修改。

二、ChangeTracker 的作用

1)DbContext 中的 ChangeTracker 组件负责管理所有被跟踪实体的状态。关键功能包括:

  1. 状态管理:跟踪实体的状态(Added, Modified, Deleted, Unchanged)。
  2. 变更检测:自动检测属性值的差异,标记需更新的实体。
  3. 导航属性跟踪:若修改关联实体(如集合或引用属性),会自动处理外键和关联表的变化。

2)查看不同操作下实体状态(增、删、改等)

var articles = dbContext.Articles.Take(3).ToArray();
var a1 = articles[0];
var a2 = articles[1];
var a3 = articles[2];

Article a4 = new Article { Title = "新增1", Content = "aaaaaaa1" };
Article a5 = new Article { Title = "新增2", Content = "aaaaaaa2" };


a1.Title += "修改标题";
dbContext.Remove(a2);
dbContext.Add(a4);

EntityEntry e1 = dbContext.Entry(a1);
EntityEntry e2 = dbContext.Entry(a2);
EntityEntry e3 = dbContext.Entry(a3);
EntityEntry e4 = dbContext.Entry(a4);
EntityEntry e5 = dbContext.Entry(a5);

Console.WriteLine(e1.State);
Console.WriteLine(e1.DebugView.LongView);
Console.WriteLine(e2.State);
Console.WriteLine(e3.State);
Console.WriteLine(e4.State);
Console.WriteLine(e5.State);

实体状态:

Modified
Article {Id: 1} Modified
    Id: 1 PK
    Content: '内容1'
    Title: '标题1修改标题' Modified Originally '标题1'
  Comments: []
Deleted
Unchanged
Added
Detached

三、 显示状态控制

1)手动设置状态

Article article = dbContext.Articles.First();
var articleEntry = dbContext.Entry(article);
articleEntry.State = EntityState.Modified; // 强制标记为已修改	
Console.WriteLine(dbContext.Entry(article).DebugView.LongView);//查看状态

实体状态:

Article {Id: 1} Modified
    Id: 1 PK
    Content: '内容1' Modified
    Title: '标题1' Modified
  Comments: []

2)部分更新:若仅需更新特定字段,可标记修改的属性

Article article = dbContext.Articles.First();
var articleEntry = dbContext.Entry(article);

articleEntry.Property(c=>c.Title).IsModified = true;
Console.WriteLine(dbContext.Entry(article).DebugView.LongView);

实体状态:

Article {Id: 1} Modified
    Id: 1 PK
    Content: '内容1'
    Title: '标题1' Modified
  Comments: []

四、性能优化策略

1)无跟踪查询(如果查询出来的对象不会被修改、删除等):使用 AsNoTracking 避免不必要的跟踪,提升查询性能

var articles = dbContext.Articles.AsNoTracking().ToList();

2)批量操作:通过 AddRange、UpdateRange 等方法减少变更检测开销

Article a4 = new Article { Title = "新增111", Content = "aaaaaaa1" };
Article a5 = new Article { Title = "新增222222", Content = "aaaaaaa2" };
await dbContext.Articles.AddRangeAsync(a4,a5);
await dbContext.SaveChangesAsync();

3)关闭自动检测:在密集更新场景中,暂时禁用自动检测

dbContext.ChangeTracker.AutoDetectChangesEnabled = false;
// 手动调用 DetectChanges() 按需检测

五、并发控制

1)EF Core 使用 乐观并发控制 处理并发冲突

  1. 配置并发令牌:在实体类中标记并发属性(如时间戳或版本号)

    public class Product
    {
        public int Id { get; set; }
        [ConcurrencyCheck]
        public byte[] Version { get; set; }
    }
    
  2. 冲突处理:在 SaveChanges 时,若数据库中的值与快照不一致,抛出
    DbUpdateConcurrencyException,开发时需处理重试或合并逻辑。


六、变更跟踪代理(高级)

EF Core 支持通过 变更跟踪代理 实现即时变更通知(需满足特定条件,如属性为 virtual):

  1. 动态代理类:在属性被修改时,代理类自动通知 ChangeTracker,无需值比较

  2. 启用方式

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    	{
    	    optionsBuilder.UseChangeTrackingProxies();
    	}
    

总结

  1. EF Core 通过 快照跟踪ChangeTracker
    的协作,自动检测实体变化,并生成高效的数据库操作。开发者可通过显式状态控制、无跟踪查询和并发配置,灵活平衡功能与性能。理解这些机制有助于优化数据操作,避免常见陷阱(如意外更新全字段或并发冲突)。

  2. DbContext会根据跟踪的实体状态,在SaveChanges()时,根据实体状态不同,生成Update、delete、insertSQL语句,把内存总的实体的变化更新到数据库中。

你可能感兴趣的:(c#,.netcore)