错误 - SqlDateTime溢出。必须在1/1/1753 12:00:00 AM和12/31/9999 11:59:59 PM之间

时间:2009-01-22 04:29:26

标签: asp.net linq-to-sql sql-server-2008

我一直在使用我编写的这段代码,并且它以最不明确的方式工作。我希望在数据库中插入一行,其中包含两列DateTime:

myrow.ApprovalDate = DateTime.Now
myrow.ProposedDate = DateTime.Now

然而,当我更新数据库时,我收到此错误:

  

SqlDateTime溢出。必须在1/1/1753 12:00:00 AM和12/31/9999 11:59:59 PM之间。

我甚至尝试从数据库中复制插入的值并将其硬编码到正在更新的对象中:

// I copied this value from the DB
myrow.ApprovalDate =  Convert.ToDateTime("2008-12-24 00:00:00.000");

仍然是同样的错误,奇怪的是,上面的技巧适用于第一次插入数据库,但从那里失败了。有什么想法正在发生什么?

14 个答案:

答案 0 :(得分:74)

C#中的DateTime是值类型,而不是引用类型,因此不能为null。但它可以是常量DateTime.MinValue,它超出了Sql Servers DATETIME数据类型的范围。

保证值类型始终具有(默认)值(零),而不必总是需要显式设置(在本例中为DateTime.MinValue)。

结论是您可能有一个未设置的DateTime值,您尝试将其传递给数据库。

DateTime.MinValue = 1/1/0001 12:00:00 AM
DateTime.MaxValue = 23:59:59.9999999, December 31, 9999, 
                    exactly one 100-nanosecond tick 
                    before 00:00:00, January 1, 10000

MSDN:DateTime.MinValue


关于Sql Server

  

日期时间
  日期和时间数据从1753年1月1日到9999年12月31日,精确到三百分之一秒(相当于3.33毫秒或0.00333秒)。值四舍五入为.000,.003或.007秒的增量

     

SMALLDATETIME
  日期和时间数据从1900年1月1日到2079年6月6日,精确到分钟。具有29.998秒或更低的smalldatetime值向下舍入到最接近的分钟; 29.999秒或更高的值向上舍入到最接近的分钟。

MSDN:Sql Server DateTime and SmallDateTime


最后,如果您发现自己将C#DateTime作为字符串传递给sql,则需要按如下方式对其进行格式化以保持最大精度并防止sql server抛出类似错误。

string sqlTimeAsString = myDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff");

更新(8年后)

考虑使用sql DateTime2数据类型,它与.net DateTime更好地对齐,日期范围0001-01-01 through 9999-12-31和时间范围00:00:00 through 23:59:59.9999999

string dateTime2String = myDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffffff");

MSDN datetime2 (Transact-SQL)

答案 1 :(得分:66)

我发现在许多数据库相关错误之后的SQL最小/最大日期中使用了以下工作:

DateTime rngMin = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;

DateTime rngMax = (DateTime)System.Data.SqlTypes.SqlDateTime.MaxValue;

答案 2 :(得分:9)

您对这两列的代码看起来不错。在该映射类上查找任何其他日期时间列。此外,启用datacontext上的日志记录以查看查询和参数。

dc.Log = Console.Out;

DateTime初始化为c#的0 - 即0001-01-01。这是由linqtosql通过sql字符串文字传输到数据库:'0001-01-01'。 Sql无法解析此日期的T-Sql日期时间。

有几种方法可以解决这个问题:

  • 确保使用SQL可以处理的值初始化所有日期时间(例如Sql的0:1900-01-01)
  • 确保可能偶尔会遗漏的任何日期时间可空日期时间

答案 3 :(得分:9)

在将.Net DateTime与SqlDateTime.MinValue或MaxValue进行比较时要小心。例如,以下内容将引发异常:

DateTime dte = new DateTime(1000, 1, 1);
if (dte >= SqlDateTime.MinValue)
    //do something

原因是MinValue返回SqlDateTime,而不是DateTime。所以.Net尝试将dte转换为SqlDateTime进行比较,因为它超出了可接受的SqlDateTime范围,所以它会抛出异常。

对此的一个解决方案是将DateTime与SqlDateTime.MinValue进行比较。

答案 4 :(得分:6)

如果您尝试将 DateTime 类型的变量设置为 null ,则会发生此错误。将变量声明为可空,即 DateTime? 。这将解决问题。

答案 5 :(得分:3)

有时为了编写更少的代码,通过将字段的默认值设置为GETDATE()NEWID(),可以使用SQL服务器设置字段(如插入日期,时间和ID)。

在这种情况下,实体类中这些字段的自动生成值属性应设置为true。

这样您就不需要在代码中设置值(防止能耗!!!)并且永远不会看到异常。

答案 6 :(得分:1)

这通常意味着将null发送到查询而不是您想要的值,您可能会尝试运行SQL事件探查器以查看从linq传递给SQL Server的确切内容。

答案 7 :(得分:1)

使用扩展方法

 public static object ToSafeDbDateDBnull(this object objectstring)
    {
        try
        {
            if ((DateTime)objectstring >= SqlDateTime.MinValue)
            {
                return objectstring;
            }
            else
            {
                return DBNull.Value;
            }
        }
        catch (Exception)
        {

            return DBNull.Value;
        }

    }

DateTime objdte = new DateTime(1000, 1, 1);
dte.ToSafeDbDateDBnull();

答案 8 :(得分:0)

如果您正在使用NHibernate,请检查可以为空的适当DateTime属性是否在映射中设置为可为空。

答案 9 :(得分:0)

我看到了同样的事情。在插入行但在更新时不会发生错误。我引用的表有两个DateTime列,它们都不可为空。

我已经让方案得到了行并立即保存(没有数据更改)。 get工作正常,但更新失败。

我们正在使用NHibernate 3.3.1.4000

答案 10 :(得分:0)

通常在进行DateTime转换或解析时会出现这种错误。检查托管应用程序的服务器中的日历设置,主要是时区和短日期格式,并确保将其设置为该位置的正确时区。希望这能解决问题。

答案 11 :(得分:0)

是否将Datetime设置为null,如DateTime?在您的模型中不会引发异常。 我就这样解决了问题

答案 12 :(得分:0)

就我而言,出现此错误是因为“表日期”列不可为空

如下:

N     = 1000000
prime = [True]*int(N**0.5) # largest prime used will be smaller than square root of N           
n     = 1

for p in range(2,len(prime)):
    if not prime[p]: continue
    prime[p*p::p] = [False]*len(prime[p*p::p]) # Eratosthenes
    if n*p < N:  n *= p                        # product of first primes
    else: break                                # while product fits within N

n   = n*(N//n)                                 # multiply to maximize n within N
phi = n                                        # compute phi(n)
for f in range(2,p):
    if prime[f]: phi -= phi//f                 # n*(1-1/p)(1-1/p) ...

if printIt:
    print(f"Max n/phi(n) from 1 to {N}: n={n} phi(n)={phi} ({n/phi})") 

为避免此错误,请将其设置为可空值

Create Table #TempTable(
 ...
 ApprovalDate datatime not null.
 ...)

答案 13 :(得分:-3)

DateTime.MinValue和DateTime.MaxValue

DateTime.MinValue = 1/1/0001 12:00:00 AM

DateTime.MaxValue = 23:59:59.9999999, December 31, 9999, 

                exactly one 100-nanosecond tick 

                before 00:00:00, January 1, 10000