如何在Entity Framework Core 6中将C# TimeOnly类型映射到SQL Server 2019的time(0)类型?
解决EF Core 6中TimeOnly类型与SQL Server 2019的迁移问题
首先,你的自定义TimeOnlyConverter逻辑本身是正确的,但EF Core 6其实已经内置了对SQL Server time类型与TimeOnly的映射支持,不需要手动实现转换器。我们来一步步分析问题和解决方案:
为什么会出现这个错误?
报错信息里提到属性被识别为DateTime类型,大概率是因为EF Core没有正确加载到你的转换器配置,或者你使用的SQL Server EF Core提供包版本存在兼容性问题。EF Core 6开始原生支持TimeOnly和DateOnly,但需要确保你的Microsoft.EntityFrameworkCore.SqlServer包是6.x的稳定版本。
优化解决方案(推荐)
直接使用EF Core 6的内置支持,只需要在ConfigureConventions中配置列类型即可,无需自定义转换器:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { // 将所有TimeOnly类型映射到SQL Server的time(0)类型(秒级精度) configurationBuilder.Properties<TimeOnly>() .HaveColumnType("time(0)"); }
这样EF Core会自动处理TimeOnly与SQL Server time类型的转换,避免手动转换器可能带来的配置遗漏问题。
如果你想保留自定义转换器
如果因为特定需求必须使用自定义转换器,建议直接在配置中使用lambda表达式简化实现,同时确保配置全局生效:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { configurationBuilder.Properties<TimeOnly>() .HaveConversion( timeOnly => new DateTime(DateOnly.MinValue.Year, DateOnly.MinValue.Month, DateOnly.MinValue.Day, timeOnly.Hour, timeOnly.Minute, timeOnly.Second), dateTime => TimeOnly.FromDateTime(dateTime)) .HaveColumnType("time(0)"); }
或者,也可以针对单个实体属性单独配置(适合局部需求):
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<PassportOffice>() .Property(p => p.OpenTime) .HasConversion( t => t.ToDateTime(DateTime.MinValue), d => TimeOnly.FromDateTime(d)) .HasColumnType("time(0)"); modelBuilder.Entity<PassportOffice>() .Property(p => p.CloseTime) .HasConversion( t => t.ToDateTime(DateTime.MinValue), d => TimeOnly.FromDateTime(d)) .HasColumnType("time(0)"); }
额外检查项
- 确认你的
Microsoft.EntityFrameworkCore.SqlServerNuGet包版本是6.x,且与EF Core版本一致; - 执行迁移前,清理项目并重新生成,确保配置代码被正确编译加载;
- 如果仍然报错,可以尝试删除现有迁移文件,重新生成迁移脚本。
内容的提问来源于stack exchange,提问作者Vitalii Nesterenko
相关产品推荐
相关产品推荐

