EF Core实体追踪,Entry数据如何成疑问?
摘要:这回终于可以 Free 了,刚好快过年了,工厂的机器也很人性化地坏了,需要供应商维修,不用测试项目了。所以老周也回家快活了几天。其实他们自己有开发团队,小改小测的他们完全可以自己弄,非要找老周麻烦。 咱们接着上次的话题聊,上次老周给大伙伴们
这回终于可以 Free 了,刚好快过年了,工厂的机器也很人性化地坏了,需要供应商维修,不用测试项目了。所以老周也回家快活了几天。其实他们自己有开发团队,小改小测的他们完全可以自己弄,非要找老周麻烦。
咱们接着上次的话题聊,上次老周给大伙伴们胡诌了一番有关实体状态追踪的基础。这一次咱们把注意力放到名为 EntityEntry 的对象上。咦,这名怎么看着这么奇葩?咱们不管它奇不奇葩,只要知道它负责保存实体对象的属性值就行了。
毕竟实体类通常就是一个普通类,EF Core 需要状态追踪功能,总不能让开发者自己去跟踪吧,所以,EF 内部会用字典数据结构来保存实体的各个属性的值。字典是个好东西,啥都能放。有时候在写 Web API 时,一些返回 JSON 结构是动态的,为它们都定义一个类来序列化是不明智的,直接拼装 JSON 有点麻烦,这时候用字典就很爽。
当实体从数据库查询出来时,EF 先为实体对象创建一个快照,表明它的原始数据。然后,当你对实体进行各种搔操作之后,调用一下DetectChanges 方法,它会扫描实体对象各个属性的值,并和当初创建的快照比较,以确定实体是否被修改(或删除)。
为了让初学的大伙伴们好理解,咱们做个对比实验。
假设有这么个实体类,它表示一本书的信息。
public class Book
{
public int BookId { get; set; }
public string Name { get; set; } = null!;
public string ISBN { get; set; } = null!;
public string Author { get; set; } = null!;
public int PubYear { get; set; }
}
然后是实现数据库上下文。
public class MyDb : DbContext
{
public DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("data source=shop.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var bookEnt = modelBuilder.Entity<Book>();
// 主键名称
bookEnt.HasKey(x => x.BookId).HasName("PK_Book");
// 字符串长度
bookEnt.Property(a => a.Name).HasMaxLength(65);
bookEnt.Property(b => b.Author).HasMaxLength(20);
bookEnt.Property(c => c.ISBN).HasMaxLength(15);
bookEnt.ToTable("tb_Books", t =>
{
// 约束
t.HasCheckConstraint("CK_Pubyear", "\"PubYear\" >= 2020 AND \"PubYear\" <= 2080");
});
}
}
上面那些都是常规操作了,大家瞄两眼就行。下面代码创建数据库并插入一条数据。
using MyDb context = new();
context.Database.EnsureCreated();
Book bb = new()
{
Name = "回魂术",
Author = "老周",
ISBN = "551269882",
PubYear = 2028
};
context.Books.Add(bb);
context.SaveChanges();
下面重头戏来了。咱们从数据库中查询出这条记录,然后改变 PubYear 属性的值。
