.NET Core EF连接MySQL时time类型返回拆分对象如何解决
问题根因
MySQL time类型在EF Core中默认映射为C# TimeSpan类型,你看到的嵌套结构化对象是JSON序列化器处理TimeSpan的默认行为,和数据库映射、EF Core逻辑无关,不需要修改生产库的字段类型,仅调整序列化配置即可解决。
推荐方案:全局配置TimeSpan序列化格式(无侵入,不影响数据库读写)
该方案不需要修改实体类、EF Core映射配置,仅调整Web API的JSON序列化规则,所有接口的TimeSpan字段都会自动输出为HH:mm:ss格式字符串。
- 自定义System.Text.Json的TimeSpan转换器,新建
TimeSpanJsonConverter.cs:
using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; public class TimeSpanJsonConverter : JsonConverter<TimeSpan> { private const string StandardTimeFormat = @"hh\:mm\:ss"; public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return TimeSpan.ParseExact(reader.GetString()!, StandardTimeFormat, CultureInfo.InvariantCulture); } public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString(StandardTimeFormat, CultureInfo.InvariantCulture)); } }
- 注册转换器到全局JSON配置:
- .NET 6+ 版本修改
Program.cs:
builder.Services.AddControllers() .AddJsonOptions(opt => { opt.JsonSerializerOptions.Converters.Add(new TimeSpanJsonConverter()); });
- .NET Core 3.1/.NET 5 版本修改
Startup.cs的ConfigureServices方法:
services.AddControllers() .AddJsonOptions(opt => { opt.JsonSerializerOptions.Converters.Add(new TimeSpanJsonConverter()); });
配置完成后重启项目,trnTime、prevTime字段就会返回"17:11:00"、"00:00:00"格式的字符串,完全符合预期,且数据库读写逻辑不受任何影响。
备选方案:单独接口用DTO映射
如果不想全局修改序列化规则,可针对该接口单独定义返回DTO,手动格式化TimeSpan字段:
- 定义返回用的DTO类:
public class DtrDto { public int LineNo { get; set; } public string EmpCode { get; set; } public int? LogType { get; set; } public DateTime? TrnDate { get; set; } public string TrnTime { get; set; } public DateTime SvrTime { get; set; } public string PrevTime { get; set; } public DateTime? PrevDate { get; set; } }
- 修改Controller接口,查询后映射为DTO返回:
[HttpGet("getalldtr")] public ActionResult<IEnumerable<DtrDto>> GetAllDtr() { return _context.Dtrs.Take(100) .Select(x => new DtrDto { LineNo = x.LineNo, EmpCode = x.EmpCode, LogType = x.LogType, TrnDate = x.TrnDate, TrnTime = x.TrnTime.ToString(@"hh\:mm\:ss"), SvrTime = x.SvrTime, PrevTime = x.PrevTime.ToString(@"hh\:mm\:ss"), PrevDate = x.PrevDate }) .ToList(); }
避坑提醒
- 不要直接把实体类里的
TrnTime、PrevTime属性类型改成string,会破坏EF Core和MySQLtime字段的映射,导致数据库读写报错。 - 如果项目用Newtonsoft.Json替代默认的System.Text.Json,只需要安装对应版本的
Microsoft.AspNetCore.Mvc.NewtonsoftJson包,注册时追加.AddNewtonsoftJson(opt => opt.SerializerSettings.Converters.Add(new TimeSpanConverter()))即可,Newtonsoft.Json自带的TimeSpan转换器默认就会序列化为HH:mm:ss格式。
内容的提问来源于stack exchange,提问作者Rak
相关产品推荐
相关产品推荐

