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

如何解决C#迁移SQL Server数据到Access时日期格式转换错误问题

解决SQL Server到Access迁移时日期格式错位的问题

这个问题的核心原因是你直接拼接日期字符串生成SQL语句,Access会依赖系统区域设置来解析日期文本,这就导致了dd/MM/yyyy格式的字符串被误解析成MM/dd/yyyy——比如12/01/2024会被当成1月12日而非12月1日。更严重的是,这种拼接写法还存在SQL注入风险,必须立刻改掉!

最佳解决方案:使用参数化查询

参数化查询是处理数据库交互的标准做法,它能彻底避免日期格式解析问题,同时杜绝SQL注入。下面是改写后的代码示例:

首先,重构你的SQL语句,用参数占位符替代直接拼接的变量:

AccessInsertCommand.CommandText = @"
INSERT INTO [Ordonnance] (
    [N_Ordonnance], [N_ASS], [NomASS], [PrénomASS], [Cat_ASS], 
    [DateFinContrat], [Nom Ayant], [Prénom Ayant], [Sexe Ayant], 
    [Date_Naiss], [Lien Parenté], [Date Saisie], [Date_Soin], 
    [Pathologie], [Nom_Méd], [Statut Assurée], [Carte N°=], 
    [DateValidation], [DateFinTraiCh], [N_Fact], [Date_Fact], 
    [N_Bord], [Nom_Phar], [Montant], [Nbre Vignettes], [Total], [Nbre Ord]
) VALUES (
    @NOrdonnance, @NAss, @NomAss, @PrenomAss, @CatAss,
    @DateFinContrat, @NomAyant, @PrenomAyant, @SexeAyant,
    @DateNaiss, @LienParente, @DateSaisie, @DateSoin,
    @Pathologie, @NomMed, @StatutAssure, @CarteNum,
    @DateValidation, @DateFinTraiCh, @NFact, @DateFact,
    @NBord, @NomPhar, @Montant, @NbreVignettes, @Total, @NbreOrd
)";

然后逐个添加参数,重点处理日期类型字段(直接传递DateTime对象,无需拼接字符串或#符号):

using System.Globalization;

// 数字类型参数
AccessInsertCommand.Parameters.AddWithValue("@NOrdonnance", Ordonnance.N_ORD);
AccessInsertCommand.Parameters.AddWithValue("@NAss", Ordonnance.NUM_ASSURE);

// 字符串类型参数(空值用DBNull.Value)
AccessInsertCommand.Parameters.AddWithValue("@NomAss", string.IsNullOrEmpty(Ordonnance.NOM_ASSURE) ? DBNull.Value : (object)Ordonnance.NOM_ASSURE);
AccessInsertCommand.Parameters.AddWithValue("@PrenomAss", string.IsNullOrEmpty(Ordonnance.PRENOM_ASSURE) ? DBNull.Value : (object)Ordonnance.PRENOM_ASSURE);
AccessInsertCommand.Parameters.AddWithValue("@CatAss", string.IsNullOrEmpty(Ordonnance.CAT_ASS) ? DBNull.Value : (object)Ordonnance.CAT_ASS);

// 重点:处理Date_Soin字段(你的问题核心字段)
if (Ordonnance.DATE_SOINS == null || string.IsNullOrEmpty(Ordonnance.DATE_SOINS.ToString()))
{
    AccessInsertCommand.Parameters.AddWithValue("@DateSoin", DBNull.Value);
}
else
{
    // 确保从SQL Server获取的日期字符串按dd/MM/yyyy解析为DateTime
    DateTime dateSoin = DateTime.ParseExact(Ordonnance.DATE_SOINS.ToString(), "dd/MM/yyyy", CultureInfo.InvariantCulture);
    AccessInsertCommand.Parameters.AddWithValue("@DateSoin", dateSoin);
}

// 其他日期字段同理处理
if (string.IsNullOrEmpty(Ordonnance.DATE_FIN_CONTRAT))
{
    AccessInsertCommand.Parameters.AddWithValue("@DateFinContrat", DBNull.Value);
}
else
{
    DateTime dateFinContrat = DateTime.ParseExact(Ordonnance.DATE_FIN_CONTRAT, "dd/MM/yyyy", CultureInfo.InvariantCulture);
    AccessInsertCommand.Parameters.AddWithValue("@DateFinContrat", dateFinContrat);
}

// 剩余参数依此类推,比如:
AccessInsertCommand.Parameters.AddWithValue("@DateSaisie", DateTime.ParseExact(Ordonnance.DATE_SAISIE, "dd/MM/yyyy", CultureInfo.InvariantCulture));
AccessInsertCommand.Parameters.AddWithValue("@Montant", string.IsNullOrEmpty(Ordonnance.MONTANT.ToString()) ? DBNull.Value : (object)Convert.ToDecimal(Ordonnance.MONTANT.ToString().Replace(",", ".")));
// ... 其他参数请按对应类型添加,空值统一用DBNull.Value

// 执行插入
AccessInsertCommand.ExecuteNonQuery();

关键注意事项

  1. 日期解析要明确格式:如果从SQL Server获取的日期是字符串类型,一定要用DateTime.ParseExact指定dd/MM/yyyy格式,避免系统区域设置干扰解析结果。如果SQL Server中的字段本身是datetime类型(不是字符串),直接传递该DateTime对象即可,无需转换。
  2. 空值处理要正确:数据库中的空值必须用DBNull.Value,而不是字符串"null",参数化查询会自动处理数据类型匹配。
  3. 彻底抛弃字符串拼接SQL:这种写法不仅容易引发格式问题,还会让你的代码暴露在SQL注入攻击下,参数化查询是行业标准的安全做法。

内容的提问来源于stack exchange,提问作者Wahéb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:30:15