【EF Core】实体跟踪

实体状态

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

SaveChanges()操作

“已分离”和“未改变”的实体,SaveChanges()忽略;
“已添加”的实体,SaveChanges() 插入数据库;
“已修改”的实体,SaveChanges() 更新到数据库;
“已删除”的实体,SaveChanges() 从数据库删除

查看实体状态

使用DbContextEntry()方法来获得实体在EF Core中的跟踪信息对象EntityEntryEntityEntry类的State属性代表实体的状态,通过DebugView.LongView属性可以看到实体的变化信息。

using (var ctx = new TestDbContext())
{
    Article article = new Article { Title = "文章1", Content = "文章1" };
    var entry = ctx.Entry(article);
    var state = entry.State;//Detached
    ctx.Add(article);
    state = entry.State;//Added
    ctx.SaveChanges();
    state = entry.State;//Unchanged
    article.Title = "文章11";
    state = ctx.Entry(article).State;//Modified

    article = ctx.Articles.FirstOrDefault();
    state = ctx.Entry(article).State;//Unchanged
}

快照更改跟踪

首次跟踪一个实体的时候,EF Core 会创建这个实体的快照。执行SaveChanges()等方法时,EF Core将会把存储的快照中的值与实体的当前值进行比较。

禁用跟踪

如果通过DbContext查询出来的对象只是用来展示,不会发生状态改变,则可以使用AsNoTracking()来 “禁用跟踪”。可以降低内存占用。

using (var ctx = new TestDbContext())
{
    var article = ctx.Articles.AsNoTracking().FirstOrDefault();
    var entry = ctx.Entry(article);
    var state = entry.State;//Detached
}

小技巧

直接更新一条记录,不查询:

Book b1 = new Book {Id=10};//跟踪通过Id定位
b1.Title = "fan";
var entry1 = ctx.Entry(b1);
entry1.Property("Title").IsModified = true;
Console.WriteLine(entry1.DebugView.LongView);
ctx.SaveChanges();

直接删除一条数据:

Book b1 = new Book { Id = 28 };
ctx.Entry(b1).State = EntityState.Deleted;
ctx.SaveChanges();

上面的技巧代码可读性、可维护性不强,而且使用不当有可能造成不容易发现的Bug。带来的性能提升也是微乎其微的,因此不推荐使用,知道即可。

posted @ 2022-04-29 22:33  .Neterr  阅读(604)  评论(0编辑  收藏  举报