SmallDateTime仅在远程测试服务器上溢出

时间:2017-04-16 17:40:10

标签: c# asp.net sql-server

我有一个应用程序,用户将数据excel文件上传到数据库表,所有列的顺序与excel和数据库表的顺序相同。

我使用OpenXML SDK进行解析,使用switch / case调整某些字段类型以避免错误。

 public static object ConvertToExpectedType(string value, SqlDbType sqlType)
        {
            switch (sqlType)
            {
                ...

            case SqlDbType.SmallDateTime:
            case SqlDbType.DateTime:
            case SqlDbType.Date:
            case SqlDbType.DateTime2:
                return ParseExcelDate(value, SqlDbType.DateTime);
            case SqlDbType.Time:
                return ParseExcelDate(value, SqlDbType.Time).TimeOfDay;

            ...

        }
    }

    public static DateTime ParseExcelDate(this string date, SqlDbType type)
    {
        if (date.Equals("null", StringComparison.InvariantCultureIgnoreCase))
            return new DateTime(1900, 01, 01);

        DateTime dt;

        if (DateTime.TryParse(date, culture, DateTimeStyles.NoCurrentDateDefault,out dt))
        {
            return dt;
        }

        double oaDate;
        if (double.TryParse(date,  NumberStyles.Float, culture,out oaDate))
        {
            return DateTime.FromOADate(oaDate);
        }

        return new DateTime(1900, 01, 01);
    }

在我的开发环境(发布和调试模式)中,应用程序运行正常,但是当我将其发布到我的服务器时,我从其中一个文件中获取此异常:

  

SqlDbType.SmallDateTime溢出。价值'12 / 31/1899 00:00:00'已经结束   范围。必须在1/1/1900 12:00:00 AM和6/6/2079 11:59:59之间   PM;

即使我将连接字符串设置为VS中的远程数据库,该应用程序也能正常工作。

之前有没有人遇到这个问题? 任何想法如何解决它或做不同的测试来确定问题所在?

完全例外

System.OverflowException: SqlDbType.SmallDateTime overflow.  Value '12/31/1899 00:00:00' is out of range.  Must be between 1/1/1900 12:00:00 AM and 6/6/2079 11:59:59 PM.
   at System.Data.SqlClient.TdsParser.WriteUnterminatedValue(Object value, MetaType type, Byte scale, Int32 actualLength, Int32 encodingByteSize, Int32 offset, TdsParserStateObject stateObj, Int32 paramSize, Boolean isDataFeed)
   at System.Data.SqlClient.TdsParser.WriteBulkCopyValue(Object value, SqlMetaDataPriv metadata, TdsParserStateObject stateObj, Boolean isSqlType, Boolean isDataFeed, Boolean isNull)
   at System.Data.SqlClient.SqlBulkCopy.ReadWriteColumnValueAsync(Int32 col)
   at System.Data.SqlClient.SqlBulkCopy.CopyColumnsAsync(Int32 col, TaskCompletionSource`1 source)
   at System.Data.SqlClient.SqlBulkCopy.CopyRowsAsync(Int32 rowsSoFar, Int32 totalRows, CancellationToken cts, TaskCompletionSource`1 source)
   at System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinued(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
   at System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsync(BulkCopySimpleResultSet internalResults, String updateBulkCommandText, CancellationToken cts, TaskCompletionSource`1 source)
   at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestContinuedAsync(BulkCopySimpleResultSet internalResults, CancellationToken cts, TaskCompletionSource`1 source)
   at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalRestAsync(CancellationToken cts, TaskCompletionSource`1 source)
   at System.Data.SqlClient.SqlBulkCopy.WriteToServerInternalAsync(CancellationToken ctoken)
   at System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServerAsync(Int32 columnCount, CancellationToken ctoken)
   at System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable table, DataRowState rowState)
   at PVINOVA_FIleUploader_v1._0.Models.MSqlServer.MSqlServerDbContext.InsertRecordsSqlBulkCopy(DataTable dt, SqlTransaction transaction, List`1 TableSchema, FileType fileType, String errLogPath)

提前致谢!

更新!!!找到有问题的字段

我将有问题的批次解压缩到CSV文件,找出错误的日期。

原始文件的值为01/01/1900,但在字段上的处理(上面提到的方法ParseExcelDate)后,字段变为12/31/1899。

此外,其他日期值与原始文件

匹配

我想到了两种可能的解决方案,但我仍然不明白为什么会发生这种情况,所以我对修复感到不舒服。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

使用OpenXML SDK解析excel中的值时,日期将为浮点数(即45231,4221)。由于字段值为1900-01-01 = 1.0 .Net转换为自己的默认值,即1899-12-30 = 1.0。

为了解决这个问题,我又在“ParseExcelDate”方法中为第一个If语句添加了一个条件

public static DateTime ParseExcelDate(this string date, SqlDbType type)
        {
            if (date.Equals("null", StringComparison.InvariantCultureIgnoreCase) || date.Equals("1.0"))
                return new DateTime(1900, 01, 01);
...

这篇文章帮助我找到了这个解决方案:What is equivalent of DateTime.ToOADate() in javascript?

但我仍然不知道它在我的本地机器上是如何工作的,而不是在服务器上