ASP.NET Core MVC 使用 EF Core 实现字段自动填充(如:添加时间 CreatedTime、更新时间 UpdatedTime)
参考
- DeepSeek
- 豆包
- 其他(由于文章是后编写的,相关参考文章未存储连接)
环境
| 软件/系统 | 版本 | 说明 |
|---|---|---|
| Windows | windows 10 专业版 22H2 64 位操作系统, 基于 x64 的处理器 | |
| Microsoft Visual Studio | Community 2022 (64 位) - Current 版本 17.14.9 | |
| Visual Studio Code | 1.102.2 | |
| Docker Engine | v28.3.2 | Docker 桌面工具 |
| Docker | 28.3.2 | |
| pgAdmin4 | 9.0 | PostgreSQL 数据库管理软件 |
| PostgreSQL | 15 | |
| .NET | 8 | |
| ASP.NET Core MVC | ASP.NET Core MVC in .NET 8.0 | |
| Microsoft.EntityFrameworkCore.Design | 8.0.18 | nuget 依赖 |
| Microsoft.EntityFrameworkCore.Tools | 8.0.18 | nuget 依赖 |
| Microsoft.VisualStudio.Web.CodeGeneration.Design | 8.0.7 | nuget 依赖 (Microsoft Visual Studio在通过模型生成控制器与视图时自动安装的依赖) |
| Npgsql.EntityFrameworkCore.PostgreSQL | 8.0.11 | nuget 依赖 |
| EFCore.NamingConventions | 8.0.3 | nuget 依赖 |
| X.PagedList.EF | 10.5.7 | nuget 依赖 |
| X.PagedList.Mvc.Core | 10.5.7 | nuget 依赖(安装 X.PagedList.EF 时自动安装) |
本项目入口文件为 Program.cs ,创建项目时为不使用顶级语句
注意
如果遇到时间存储出现Cannot write DateTime with Kind=Unspecified to PostgreSQL type 'timestamp with time zone', only UTC is supported. 问题时,请参考《ASP.NET Core MVC 解决 EF Core 连接 PostgreSQL 失败与数据库存储 DateTime 字段出现 Cannot write DateTime with Kind=Unspecified to PostgreSQL type 'timestamp with time zone', only UTC is supported. 问题》
正文
- 本文以
Admin表作为示例,定义Admin模型using Microsoft.EntityFrameworkCore; using NightMarketPlatformWeb.Enums; using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace NightMarketPlatformWeb.Models { /// <summary> /// 管理员管理模型 /// </summary> [Table("admins")] // 表备注 [Comment("管理员管理表")] // 普通索引 //[Index(nameof(AreaName))] // 普通索引并命名 //[Index(nameof(AreaName), Name = "AreaName")] // 唯一索引 [Index(nameof(AdminName, IsUnique = true))] // 复合唯一索引 [Index(nameof(AdminName), nameof(AdminPhoneNumber), IsUnique = true)] public class AdminModel : BaseModel { /// <summary> /// 主键 /// </summary> [Key] public int Id { get; set; } /// <summary> /// 管理员名称 /// </summary> [Required] // 字段备注 [Comment("管理员名称")] // 显示名称 [Display(Name = "管理员名称")] public string AdminName { get; set; } = string.Empty; /// <summary> /// 管理员账号/管理员联系方式 /// </summary> [Required] // 字段备注 [Comment("管理员账号/联系方式")] // 显示名称 [Display(Name = "管理员账号/联系方式")] public string AdminPhoneNumber { get; set; } = string.Empty; /// <summary> /// 管理员密码 /// </summary> [Required] // 长度验证 (如果这里设置了就会导致数据表出问题,把校验放到修改dto中) //[StringLength(16, MinimumLength = 8, ErrorMessage = " {0} 区间为 {1} - {2}.")] // 字段备注 [Comment("管理员密码")] // 显示名称 [Display(Name = "管理员密码")] public string AdminPassword { get; set; } = string.Empty; /// <summary> /// 是否启用 /// </summary> // 字段备注 [Comment("是否启用")] // 显示名称 [Display(Name = "是否启用")] public bool Enabled { get; set; } = true; } public class BaseModel { /// <summary> /// 创建时间 /// </summary> [DataType(DataType.DateTime)] // 字段备注 [Comment("创建时间")] // 显示名称 [Display(Name = "创建时间")] // 只在插入时填充 //[DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedTime { get; set; } /// <summary> /// 更新时间 /// </summary> [DataType(DataType.DateTime)] // 显示名称 [Display(Name = "更新时间")] // 字段备注 [Comment("更新时间")] // 每次更新时填充 //[DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime UpdatedTime { get; set; } /// <summary> /// 删除时间 /// </summary> [DataType(DataType.DateTime)] // 显示名称 [Display(Name = "删除时间")] // 字段备注 [Comment("删除时间")] public DateTime? DeletedTime { get; set; } } } - 重写项目
DbContext类的SaveChanges、SaveChangesAsync方法。(相关不需要的内容已注释)using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using NightMarketPlatformWeb.Models; using System; using System.Diagnostics; using System.Reflection.Metadata; using System.Xml.Linq; namespace NightMarketPlatformWeb.Data { public class ApplicationDbContext : IdentityDbContext { public DbSet<AdminModel> Admins { get; set; } //public DbSet<AreaModel> Areas { get; set; } //public DbSet<LesseeModel> Lessees { get; set; } //public DbSet<LogModel> Logs { get; set; } //public DbSet<SettingModel> Settings { get; set; } //public DbSet<StallModel> Stalls { get; set; } public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 配置摊位-用户关系 //modelBuilder.Entity<StallModel>() // .HasOne(s => s.Lessee) // 一个摊位属于一个用户 // .WithMany(l => l.Stalls) // 一个用户有多个摊位 // .HasForeignKey(s => s.LesseeId) // 明确指定外键属性 // .OnDelete(DeleteBehavior.Restrict); // 禁止级联删除 //// 配置摊位-区域关系 //modelBuilder.Entity<StallModel>() // .HasOne(s => s.Area) // 一个摊位属于一个区域 // .WithMany(a => a.Stalls) // 一个区域有多个摊位 // .HasForeignKey(s => s.AreaId) // 明确指定外键属性 // .OnDelete(DeleteBehavior.Restrict); // 禁止级联删除 } /// <summary> /// 重写savechangs /// </summary> /// <returns></returns> public override int SaveChanges() { SetSystemField(); return base.SaveChanges(); } /// <summary> /// 重写SaveChangesAsync /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)) { SetSystemField(); return await base.SaveChangesAsync(); } /// <summary> /// 重写 SaveChanges /// 时间填充 https://blog.csdn.net/qq_37214567/article/details/120288608 https://www.codeleading.com/article/79544088425/ /// 忽略null https://developer.aliyun.com/article/676711 /// </summary> /// <returns></returns> public void SetSystemField() { //自动修改 CreateTime,UpdateTime var entityEntries = ChangeTracker.Entries().ToList(); foreach (var entry in entityEntries) { // 新增自动填充时间字段 if (entry.State == EntityState.Added) { if (entry.Metadata.FindProperty(nameof(BaseModel.CreatedTime)) != null) { Entry(entry.Entity).Property(nameof(BaseModel.CreatedTime)).CurrentValue = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc); } if (entry.Metadata.FindProperty(nameof(BaseModel.UpdatedTime)) != null) { Entry(entry.Entity).Property(nameof(BaseModel.UpdatedTime)).CurrentValue = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc); } } // 更新自动填充时间字段 if (entry.State == EntityState.Modified) { if (entry.Metadata.FindProperty(nameof(BaseModel.CreatedTime)) != null) { Entry(entry.Entity).Property(nameof(BaseModel.CreatedTime)).IsModified = false; } if (entry.Metadata.FindProperty(nameof(BaseModel.UpdatedTime)) != null) { Entry(entry.Entity).Property(nameof(BaseModel.UpdatedTime)).CurrentValue = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Utc); } } } } } } - 重启项目,在数据新增、更新就会自动更新时间戳了
预览
- 数据参考

博 主 :夏秋初
地 址 :https://www.cnblogs.com/xiaqiuchu/p/19007676
如果对你有帮助,可以点一下 推荐 或者 关注 吗?会让我的分享变得更有动力~
转载时请带上原文链接,谢谢。
地 址 :https://www.cnblogs.com/xiaqiuchu/p/19007676
如果对你有帮助,可以点一下 推荐 或者 关注 吗?会让我的分享变得更有动力~
转载时请带上原文链接,谢谢。

浙公网安备 33010602011771号