EF Core 8中如何设置DateTime类型列的精度?
EF Core 8.0.2 遗留代码重构方案
你的初始方案仅能覆盖原有代码中默认设置datetime2(3)的场景,但丢失了对标记为DateAttribute.Date的属性设置date列类型的逻辑。如果你的项目中存在这类标记了日期类型的属性,直接使用SetPrecision(3)会导致列类型不符合预期;如果没有这类属性,该方案可以正常工作。
以下是更完整的重构实现,完全对齐原有代码的逻辑:
方案一:保留遍历模型的写法
通过EF Core的关系数据库扩展方法,同时处理date和datetime2(3)两种场景:
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; foreach (var property in modelBuilder.Model.GetEntityTypes() .SelectMany(x => x.GetProperties()) .Where(x => x.ClrType == typeof(DateTime) || x.ClrType == typeof(DateTime?))) { // 检查属性是否标记了DateAttribute.Date注解 var dateAnnotation = property.GetAnnotations() .Select(x => x.Value is not null ? (string)x.Value : string.Empty) .FirstOrDefault(x => x == DateAttribute.Date); if (!string.IsNullOrEmpty(dateAnnotation)) { // 设置列类型为SQL的date类型 property.SetColumnType("date"); } else { // 设置精度3,对应SQL的datetime2(3) property.SetPrecision(3); } }
注意:
SetColumnType是Microsoft.EntityFrameworkCore.Relational包中的扩展方法,需要确保项目已引用该包。
方案二:使用EF Core约定(更优雅的现代写法)
通过自定义属性配置约定,自动应用规则,无需手动遍历模型:
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Microsoft.EntityFrameworkCore.Metadata.Builders; public class DateTimeColumnConvention : IPropertyConfigurationConvention { public void ProcessPropertyConfiguration(IConventionPropertyBuilder propertyBuilder, IConventionContext<IConventionPropertyBuilder> context) { var property = propertyBuilder.Metadata; // 仅处理DateTime/DateTime?类型属性 if (property.ClrType != typeof(DateTime) && property.ClrType != typeof(DateTime?)) return; var dateAnnotation = property.GetAnnotations() .Select(x => x.Value is not null ? (string)x.Value : string.Empty) .FirstOrDefault(x => x == DateAttribute.Date); if (!string.IsNullOrEmpty(dateAnnotation)) { propertyBuilder.SetColumnType("date", fromDataAnnotation: false); } else { propertyBuilder.SetPrecision(3, fromDataAnnotation: false); } } } // 在DbContext的OnConfiguring中注册约定 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer("你的连接字符串") .AddConventions(builder => { builder.Add(new DateTimeColumnConvention()); }); }
关键说明
- EF Core中,对
DateTime类型设置SetPrecision(3)会自动映射为SQL Server的datetime2(3),和原有代码的默认行为完全一致。 - 对于需要映射为
date类型的属性,必须显式调用SetColumnType("date"),因为date类型不支持精度设置。
内容的提问来源于stack exchange,提问作者freshbm
相关产品推荐
相关产品推荐

