You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:05:09