千家信息网

Entity Framework Core如何生成列并跟踪列记录

发表于:2026-11-05 作者:千家信息网编辑
千家信息网最后更新 2026年11月05日,本文小编为大家详细介绍"Entity Framework Core如何生成列并跟踪列记录",内容详细,步骤清晰,细节处理妥当,希望这篇"Entity Framework Core如何生成列并跟踪列记录
千家信息网最后更新 2026年11月05日Entity Framework Core如何生成列并跟踪列记录

本文小编为大家详细介绍"Entity Framework Core如何生成列并跟踪列记录",内容详细,步骤清晰,细节处理妥当,希望这篇"Entity Framework Core如何生成列并跟踪列记录"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版发布时,功能可能存在变动。

当您设计数据库时,有时需要添加列以跟踪记录何时更改,以及谁进行了更改。例如,您添加以下列:

  • CreatedAt

  • CreatedBy

  • LastUpdatedAt

  • LastUpdatedBy

您可以轻松地使用默认值和触发器来处理CreatedAt和LastUpdatedAt列。老实说,创建触发器是件无聊的事情,你也不想自己做。此外,很难设置用户名,因为它是应用程序的信息;实际上,在Web程序的上下文中,它们只是连接到数据库的一个用户,因此,您无法使用数据库中CURRENT_USER函数设置跟踪列的值。

当然,您不想访问这个属性。相反,您希望 Entity Framework 为您自动执行,所以,解决的办法是调用SaveChanges或SaveChangesAsync方法之前自动设置这些属性的值。在模型中有多种方法处理这些属性:您可以在模型中添加读写(R/W)属性;您也可以使用只读(R/O)属性;还有一种方案,您可以使用阴影(Shadow)属性。在最后一种方案中,是将列不映射到模型中的属性,只有 Entity Framework 才知道这些属性。是的,EF Core 非常灵活:)

我们用 Entity Framework 实现这3种方案!

读写属性

在这种情况下,实体将具有读/写属性。这意味着,您可以在代码中更改属性的值。

public interface ITrackable{    DateTime CreatedAt { get; set; }    string CreatedBy { get; set; }    DateTime LastUpdatedAt { get; set; }    string LastUpdatedBy { get; set; }}public class Post : ITrackable{    public int Id { get; set; }    public string Title { get; set; }    public string Content { get; set; }    public DateTime CreatedAt { get; set; }    public string CreatedBy { get; set; }    public DateTime LastUpdatedAt { get; set; }    public string LastUpdatedBy { get; set; }}

现在,我们将更改SaveChanges方法的默认行为来设置跟踪属性的值。要小心,有两个方法要重写:SaveChanges和异步方法SaveChangesAsync。在代码中遍历上下文中跟踪的实体,并根据状态设置跟踪属性的值。代码非常简单:

public class BloggingContext : DbContext{    public DbSet Posts { get; set; }    public override int SaveChanges(bool acceptAllChangesOnSuccess)    {        OnBeforeSaving();        return base.SaveChanges(acceptAllChangesOnSuccess);    }    public override Task SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))    {        OnBeforeSaving();        return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);    }    private void OnBeforeSaving()    {        var entries = ChangeTracker.Entries();        foreach (var entry in entries)        {            if (entry.Entity is ITrackable trackable)            {                var now = DateTime.UtcNow;                var user = GetCurrentUser();                switch (entry.State)                {                    case EntityState.Modified:                        trackable.LastUpdatedAt = now;                        trackable.LastUpdatedBy = user;                        break;                    case EntityState.Added:                        trackable.CreatedAt = now;                        trackable.CreatedAt = user;                        trackable.LastUpdatedAt = now;                        trackable.LastUpdatedBy = user;                        break;                }            }        }    }    private string GetCurrentUser()    {        return "UserName"; // TODO implement your own logic    }}

这个方案有个不容忽视的问题,属性是可写的,您不希望在代码中设置属性的值。让我们看看如何使用只读属性。

只读属性

Entity Framework Core 允许将列映射到字段。这样,您可以使用只读属性,我们来修改 Post类:

public class Post{    private DateTime _createdAt;    private string _createdBy;    private DateTime _lastUpdatedAt;    private string _lastUpdatedBy;    public int Id { get; set; }    public string Title { get; set; }    public string Content { get; set; }    public DateTime CreatedAt => _createdAt;    public string CreatedBy => _createdBy;    public DateTime LastUpdatedAt => _lastUpdatedAt;    public string LastUpdatedBy => _lastUpdatedBy;}

上面的代码有点麻烦,但属性现在是只读的。您需要指引 Entity Framework 使用这些字段来设置列的值。

public class BloggingContext : DbContext{    public DbSet Posts { get; set; }    protected override void OnModelCreating(ModelBuilder modelBuilder)    {        base.OnModelCreating(modelBuilder);        modelBuilder.Entity()            .Property(post => post.CreatedAt)            .HasField("_createdAt");        modelBuilder.Entity()            .Property(post => post.CreatedBy)            .HasField("_createdBy");        modelBuilder.Entity()            .Property(post => post.LastUpdatedAt)            .HasField("_lastUpdatedAt");        modelBuilder.Entity()            .Property(post => post.LastUpdatedBy)            .HasField("_lastUpdatedBy");    }}

您不能像以前那样实现OnBeforeSaving方法,因为属性没有setter。不过,您可以使用 ChangeTracker来指引 Entity Framework 为属性设置值。这种方式无需访问属性或字段。

    private void OnBeforeSaving()    {        var entries = ChangeTracker.Entries();        foreach (var entry in entries)        {            if (entry.Entity is Post post)            {                var now = DateTime.UtcNow;                var user = GetCurrentUser();                switch (entry.State)                {                    case EntityState.Modified:                        entry.CurrentValues["LastUpdatedAt"] = now;                        entry.CurrentValues["LastUpdatedBy"] = user;                        break;                    case EntityState.Added:                        entry.CurrentValues["CreatedAt"] = now;                        entry.CurrentValues["CreatedBy"] = user;                        entry.CurrentValues["LastUpdatedAt"] = now;                        entry.CurrentValues["LastUpdatedBy"] = user;                        break;                }            }        }    }}

我认为应是使用的方式,因为这种方式很清晰。

不定义属性

在某些情况下,您可能需要设置列的值而不在模型中定义属性。例如,您可能会公开最后更新的日期,但不会显示谁做了更改。Entity Framework Core 可以通过使用阴影(Shadow )属性来处理这个。阴影属性在OnModelCreating方法中声明,但在类中不存在。您可以使用ChangeTracker读取和写入阴影属性的值。

public class Post{    public int Id { get; set; }    public string Title { get; set; }    public string Content { get; set; }}
public class BloggingContext : DbContext{    protected override void OnModelCreating(ModelBuilder modelBuilder)    {        base.OnModelCreating(modelBuilder);        // Declare properties        modelBuilder.Entity().Property("CreatedAt");        modelBuilder.Entity().Property("CreatedBy");        modelBuilder.Entity().Property("LastUpdatedAt");        modelBuilder.Entity().Property("LastUpdatedBy");    }    private void OnBeforeSaving()    {        var entries = ChangeTracker.Entries();        foreach (var entry in entries)        {            if (entry.Entity is Post post)            {                var now = DateTime.UtcNow;                var user = GetCurrentUser();                switch (entry.State)                {                    case EntityState.Modified:                        entry.CurrentValues["LastUpdatedAt"] = now;                        entry.CurrentValues["LastUpdatedBy"] = user;                        break;                    case EntityState.Added:                        entry.CurrentValues["CreatedAt"] = now;                        entry.CurrentValues["CreatedBy"] = user;                        entry.CurrentValues["LastUpdatedAt"] = now;                        entry.CurrentValues["LastUpdatedBy"] = user;                        break;                }            }        }    }}

读到这里,这篇"Entity Framework Core如何生成列并跟踪列记录"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。

属性 跟踪 方法 代码 方案 模型 阴影 处理 生成 字段 数据 数据库 文章 方式 上下 上下文 内容 实体 情况 用户 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 湖北九亚互联网络科技有限公司 互联网科技工作委员会副主任毛军 互联网核心科技是什么 互联网 科技 科技与互联网发展 北京互联网科技有限公司 中正互联网科技招聘 互联网实体化科技化 西藏七维空间互联网科技有限公司 剑昆互联网络科技有限公司临桂 互联网大会黑科技排名 互联网校园科技培训 互联网科技与管理 佛山市翊博互联网络科技有限公司 华中科技大学互联网的牛人 国产互联网科技公司 中国科技和美国互联网 上海互联网科技园景观 广东猫王互联网科技有限公司电话 东风日产互联网科技公司叫什么 喔噻互联网科技有限公司 科技互联网公司装修 互联网最新的科技有限公司 海南购全球互联网科技 科技互联网大厂 中科明德北京互联网科技 四川互联网展示科技馆设计 互联网科技年终奖 艺电能源互联网科技有限公司招聘 保山浩联互联网科技有限公司
0