使用Dapper向HttpGet传递DateOnly参数时遇日期格式及类型兼容问题
解决Dapper HttpGet接口日期参数格式兼容问题
一、配置ASP.NET Core支持多格式日期绑定
ASP.NET Core默认日期解析规则较严格,需自定义模型绑定器识别常见日期格式(如2023-04-30、04-30-2023、04/30/2023、2023-04-30T00:00:00)。
实现自定义绑定逻辑
在Program.cs中添加以下代码:
builder.Services.AddControllers() .AddMvcOptions(options => { // 注入自定义日期模型绑定器 options.ModelBinderProviders.Insert(0, new CustomDateModelBinderProvider()); }); // 绑定器提供者 public class CustomDateModelBinderProvider : IModelBinderProvider { public IModelBinder GetBinder(ModelBinderProviderContext context) { var modelType = context.Metadata.ModelType; // 支持DateTime、DateTime?、DateOnly、DateOnly?类型 if (modelType == typeof(DateTime) || modelType == typeof(DateTime?) || modelType == typeof(DateOnly) || modelType == typeof(DateOnly?)) { return new CustomDateModelBinder(); } return null; } } // 核心绑定逻辑 public class CustomDateModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueResult == ValueProviderResult.None) return Task.CompletedTask; var dateStr = valueResult.FirstValue; if (string.IsNullOrEmpty(dateStr)) { bindingContext.Result = ModelBindingResult.Success(null); return Task.CompletedTask; } // 定义支持的日期格式列表 var formats = new[] { "yyyy-MM-dd", "MM-dd-yyyy", "MM/dd/yyyy", "yyyy-MM-ddTHH:mm:ss", "yyyy-MM-ddTHH:mm:ss.fff" }; var modelType = bindingContext.Metadata.ModelType; if (modelType == typeof(DateOnly) || modelType == typeof(DateOnly?)) { if (DateOnly.TryParseExact(dateStr, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateOnly)) { bindingContext.Result = ModelBindingResult.Success(dateOnly); } else { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "无效日期格式,请使用yyyy-MM-dd、MM-dd-yyyy等格式"); } } else { if (DateTime.TryParseExact(dateStr, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTime)) { bindingContext.Result = ModelBindingResult.Success(dateTime); } else { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "无效日期格式,请使用yyyy-MM-dd、MM-dd-yyyy等格式"); } } return Task.CompletedTask; } }
二、修复实体类与数据库列的映射问题
实体类MyTable的theDate字段与数据库AsOfDate列名称不匹配,Dapper默认按名称严格映射,需二选一解决:
方案1:修改SQL查询语句,添加列别名
select ID as Id, AsOfDate as theDate, Sales from MyTable where asofdate = @someDate
方案2:使用Dapper特性指定列映射
修改实体类:
public class MyTable { public int Id { get; set; } [Column("AsOfDate")] public DateTime? theDate { get; set; } public decimal Sales { get; set; } }
三、正确适配DateOnly类型(可选)
若想用DateOnly替代DateTime?,需为Dapper添加类型映射支持:
添加Dapper DateOnly类型处理器
在Program.cs中配置:
// 注册DateOnly类型处理器 SqlMapper.AddTypeHandler(new DateOnlyTypeHandler()); SqlMapper.AddTypeHandler(new NullableDateOnlyTypeHandler()); // 处理非空DateOnly public class DateOnlyTypeHandler : SqlMapper.TypeHandler<DateOnly> { public override DateOnly Parse(object value) { return DateOnly.FromDateTime((DateTime)value); } public override void SetValue(IDbDataParameter parameter, DateOnly value) { parameter.DbType = DbType.Date; parameter.Value = value.ToDateTime(TimeOnly.MinValue); } } // 处理可空DateOnly public class NullableDateOnlyTypeHandler : SqlMapper.TypeHandler<DateOnly?> { public override DateOnly? Parse(object value) { if (value == null || value == DBNull.Value) return null; return DateOnly.FromDateTime((DateTime)value); } public override void SetValue(IDbDataParameter parameter, DateOnly? value) { parameter.DbType = DbType.Date; parameter.Value = value.HasValue ? value.Value.ToDateTime(TimeOnly.MinValue) : DBNull.Value; } }
修改实体类字段类型
public class MyTable { public int Id { get; set; } [Column("AsOfDate")] public DateOnly? theDate { get; set; } public decimal Sales { get; set; } }
四、接口参数传递注意事项
控制器接口无需手动转换日期格式,只要模型绑定成功,Dapper会自动将DateTime?或DateOnly?参数转换为SQL兼容的date类型,确保查询语句中参数名与传递的匿名对象属性一致即可。
内容的提问来源于stack exchange,提问作者HALO
相关产品推荐
相关产品推荐

