日期字段含空值时修改模型日期格式及解决转换报错方案
问题描述
在模型的日期属性上添加了如下数据注解特性:
[DisplayFormat(DataFormatString = "{0:dd-MMM-YYYY HH:mm:ss}", ApplyFormatInEditMode = true)] public string Upload_Date { get; set; }
但当该日期字段存在空值时,执行存储过程代码无法返回数据:
IEnumerable<HistoryList> HistoryList = await _SQLHelper.GetRecordsAsync<HistoryList>("[dbo].[USP_LIST_HISTORY]", parameters); public async Task<List<T>> GetRecordsAsync<T>(string spName, List<ParameterInfo> parameters) { //... recordList = await Task.FromResult(SqlMapper.QueryAsync<T>(objConnection, spName, p, commandType: CommandType.StoredProcedure).Result.ToList()); return recordList; }
执行到以下代码时出现错误:
recordList = await Task.FromResult(SqlMapper.QueryAsync<T>(objConnection, spName, p, commandType: CommandType.StoredProcedure).Result.ToList());
错误提示:
String '' was not recognized as a valid DateTime.
请问在日期列包含空值的场景下,如何修改日期格式并解决该问题?
解决方案
1. 修正模型属性类型(最优方案)
将Upload_Date的类型从string改为DateTime?(可空DateTime类型),让Dapper直接映射数据库的空日期值,避免字符串转换报错:
[DisplayFormat(DataFormatString = "{0:dd-MMM-yyyy HH:mm:ss}", ApplyFormatInEditMode = true)] public DateTime? Upload_Date { get; set; }
注意:格式字符串中的YYYY要改为yyyy,YYYY是基于周的年份,日常日期格式化用yyyy更准确。
2. 保留string类型的兼容处理
如果业务需求必须使用string类型,可通过Dapper自定义类型转换器处理空字符串:
// 全局注册类型转换器 SqlMapper.AddTypeHandler(new StringToNullableDateTimeHandler()); public class StringToNullableDateTimeHandler : SqlMapper.TypeHandler<DateTime?> { private readonly string _format = "dd-MMM-yyyy HH:mm:ss"; public override DateTime? Parse(object value) { if (value == null || string.IsNullOrWhiteSpace(value.ToString())) return null; return DateTime.ParseExact(value.ToString(), _format, CultureInfo.InvariantCulture); } public override void SetValue(IDbDataParameter parameter, DateTime? value) { if (!value.HasValue) parameter.Value = DBNull.Value; else parameter.Value = value.Value.ToString(_format, CultureInfo.InvariantCulture); } }
3. 存储过程层面优化
在USP_LIST_HISTORY中,将空字符串形式的日期转换为NULL,从源头避免转换错误:
SELECT -- 其他字段 CASE WHEN Upload_Date = '' THEN NULL ELSE Upload_Date END AS Upload_Date FROM YourTargetTable
4. 修复异步代码的错误写法
原代码中await Task.FromResult(QueryAsync(...).Result)是错误的异步实现,会引发死锁风险,应直接使用await:
recordList = await SqlMapper.QueryAsync<T>(objConnection, spName, p, commandType: CommandType.StoredProcedure); return recordList.ToList();
内容的提问来源于stack exchange,提问作者Lim
相关产品推荐
相关产品推荐

