如何识别列抛出 System.Data.SqlClient.SqlException? (将 datetime2 数据类型转换为 datetime 数据类型)

Posted

技术标签:

【中文标题】如何识别列抛出 System.Data.SqlClient.SqlException? (将 datetime2 数据类型转换为 datetime 数据类型)【英文标题】:How to identify column throwing System.Data.SqlClient.SqlException? (conversion of a datetime2 data type to a datetime data type) 【发布时间】:2015-03-05 21:28:25 【问题描述】:

我已经覆盖了我的ApplicationDbContext.SaveChanges() 方法。这通过在黄色和白色错误应用程序错误屏幕上提供立即可见的错误消息来帮助我。

但是当DateTime 列出现验证错误时,catch 子句似乎没有被激活。

这是为什么呢?以及如何识别无效列?

覆盖方法

public partial class ApplicationDbContext 

    public override int SaveChanges()
    
        try
        
            return base.SaveChanges();  //**error is thrown here**//
        
        catch (DbEntityValidationException ex)
        
            var sb = new StringBuilder();

            foreach (var failure in ex.EntityValidationErrors)
            
                sb.AppendFormat("0 failed validation\n", failure.Entry.Entity.GetType());
                foreach (var error in failure.ValidationErrors)
                
                    sb.AppendFormat("- 0 : 1", error.PropertyName, error.ErrorMessage);
                    sb.AppendLine();
                
            

            throw new DbEntityValidationException(
                "Entity Validation Failed - errors follow:\n" +
                sb.ToString(), ex
                ); 
        
    

但是,DateTime 列未引发异常,但似乎未激活 catch 块。

【问题讨论】:

你没有捕捉到它的原因是被捕捉到的DbEntityValidationException 与被抛出的SqlException。解决办法差不多是certainly one of these causes 谢谢。有什么我可以添加到发布的代码中来让我挂钩 SqlException 的吗?我真的只想访问导致异常的属性/字段名称。 令人讨厌的是,Sql Server 实际上并没有列出错误的列名 AFAIK。如果您能够在执行语句(或粘贴到 LinqPad)时运行 Sql Profiler,则可以获取实际的 Sql。但可能的候选者是 DateTime 尚未设置为 > 1753 (例如,未初始化为默认日期时间) 真可惜。嗯,很高兴知道。您的组合 cmets 为我提供了答案。如果你想把它们组合成我可以这样标记。 【参考方案1】:

TL;DR

如果您使用 Sql DATETIME 列,请将验证添加到持久实体上的 .Net DateTime 属性以确保值在 .SaveChanges() 之前的 17539999 之间 否则,将 Sql 存储更改为 DATEDATETIME2,具体取决于您的精度要求。

详细说明 鉴于Sql Server DateTime 数据类型只能存储1753 - 9999 范围内的日期,而.Net DateTime 结构可以存储更大的动态范围,而higher precision,即并非所有.Net DateTimes 都可以存储在Sql Server 中@ 987654334@。

EF 实体上的 .Net DateTime 属性特别容易出现此错误,因为 default(DateTime) 是 0001/01/01。

因此,优先使用DATETIME2DATE 存储替换DATETIME 列。

因此,在 > Sql 2005 RDBMS 上,实体框架将 default 转换为 Sql DATETIME2 数据类型,因为这将允许存储超出 DATETIME 提供的有限范围,并且更接近 .Net 数据类型.

但是,如果您确实有一个包含DATETIME 列的现有表并且您是attempt to bind an 'out of band' DateTime value,那么令人讨厌的是,Sql Server 实际上并没有列出错误的列名。如果您能够在执行语句(或粘贴到 LinqPad)时运行 Sql Profiler,则可以获取实际的 Sql。但可能的候选者是尚未设置为 > 1753 的 DateTime(例如,未初始化为默认 DateTime)。

您没有捕捉到Exception 的原因是因为catch DbEntityValidationException 与抛出的SqlException 之间的脱节。

【讨论】:

那批信息比 cmets 还要好——非常感谢【参考方案2】:

如果我没记错的话,您在 MSSQL 中使用的是 smalldatetime,在某些情况下可能会引发此错误。 检查this 线程以获得答案。

尝试查看catch(Exception ex),您将能够看到确切的错误消息。

【讨论】:

我是否可以在当前的语句中添加一个额外的 catch 子句?所以我需要一个来捕捉DbEntityValidationException,另一个来捕捉Exception

以上是关于如何识别列抛出 System.Data.SqlClient.SqlException? (将 datetime2 数据类型转换为 datetime 数据类型)的主要内容,如果未能解决你的问题,请参考以下文章

Cassandra 通过主键查询和列抛出错误

DataTable - 附加附加列抛出一些异常错误

使用FlatFileItemReader读取csv文件,遇到空列抛出异常

JPA 查询对不在查询中的列抛出“未找到”错误

即使将其标记为已计算,计算列抛出也无法更新错误

如何使用 .NET 创建 JSON 数据?