调用_tld.SaveChanges()时SqlException异常的解决方案咨询
调用_tld.SaveChanges();时出现如下错误:
SqlException: 将datetime类型转换为datetime2数据类型时导致值超出范围。语句已终止。
项目采用Entity Framework数据库优先模式和SQL Server,求该问题的解决方案。
异常相关代码
public static Result SavePendingTransactionsData(transaction[] model) { Authorize authorize = new Authorize(); using (TechLogisticsEntities _tld = new TechLogisticsEntities()) { try { foreach (var item in model) { L_ROD_AsTwentyFourTransaction asTwentyFourTransaction = new L_ROD_AsTwentyFourTransaction(); asTwentyFourTransaction.TransactionNumber = item.transactionNumber; asTwentyFourTransaction.TransactionType = item.transactionType; asTwentyFourTransaction.TransactionDate = item.entryTransactionDate; asTwentyFourTransaction.VehiclePlate = item.VCRegistrationNumber; asTwentyFourTransaction.VehicleId = int.Parse(item.VCNumber); //asTwentyFourTransaction.TransactionAmount = //asTwentyFourTransaction.CurrencyId = //asTwentyFourTransaction.CurrencyCode = //asTwentyFourTransaction.GrossAmount = //asTwentyFourTransaction.TransactionValue = //asTwentyFourTransaction.Unit = //asTwentyFourTransaction.TransactionCountryName = //asTwentyFourTransaction.TransactionCountryCode = //asTwentyFourTransaction.TransactionLocation = //asTwentyFourTransaction.ObuId = //2 olan asTwentyFourTransaction.StatusId = 1; //asTwentyFourTransaction.StatusCode = _tld.L_ROD_AsTwentyFourTransaction.Add(asTwentyFourTransaction); _tld.SaveChanges(); } return new Result() { IsSuccess = true }; } catch (Exception ex) { return new Result() { IsSuccess = false, UserMessage = ex.Message }; } } }
这个错误的核心原因是:SQL Server的datetime类型范围为1753年1月1日 ~ 9999年12月31日,而.NET的DateTime默认值是0001年1月1日,当EF将该默认值转换为SQL的datetime2(范围更大)后插入datetime字段时,就会触发范围超出的报错。结合你的代码,可按以下方式解决:
1. 校验并修正TransactionDate的赋值
确认item.entryTransactionDate是否为有效日期,是否存在DateTime.MinValue(0001-01-01)或早于1753-01-01的情况。如果是,给它设置符合SQL datetime范围的默认值:
// 若entryTransactionDate无效,替换为当前时间或合法起始日期 asTwentyFourTransaction.TransactionDate = item.entryTransactionDate == DateTime.MinValue ? DateTime.Now : item.entryTransactionDate;
2. 处理未赋值的日期字段
代码中存在大量注释未赋值的字段,需检查这些字段对应的数据库列是否为datetime类型且不允许为NULL。如果是未赋值的非空datetime字段,EF会自动填充DateTime.MinValue,导致插入失败。解决方式二选一:
- 在数据库中将这些字段设置为允许NULL;
- 在实体类中给这些字段设置合法默认值(如
DateTime.Now或1753-01-01之后的日期)。
3. 将数据库字段类型改为datetime2(推荐)
如果业务允许,直接把数据库中对应的datetime字段改为datetime2类型。datetime2的范围与.NET的DateTime完全匹配(0001年1月1日 ~ 9999年12月31日),从根源避免类型转换的范围问题。操作步骤:
- 打开SQL Server Management Studio,找到目标表和字段;
- 修改字段类型为
datetime2(可保留原有精度,如datetime2(7)); - 在EF数据库优先模式下,重新从数据库生成实体模型。
4. 配置EF的日期转换规则
若不想修改数据库,可在EF模型配置中指定字段使用datetime类型,避免自动转换为datetime2。在实体配置类中添加:
modelBuilder.Entity<L_ROD_AsTwentyFourTransaction>() .Property(t => t.TransactionDate) .HasColumnType("datetime");
或者在EDMX模型文件中,找到对应属性,将其Type设置为datetime而非datetime2。
内容的提问来源于stack exchange,提问作者melike aslan

