4

我一方面有一个 Access 数据库,其中Tbl_Application.id_connexion有一个Guid类型的字段(在 ms Access 术语中称为“复制 ID”)。

我正在通过一个DataRow[]数组从这个 Tbl_Application 表中收集一些数据,dr_Tbl_Application. 以下代码读取第一个 DataRow:

private Guid? mid_connexion = null;
mid_connexion = (Guid)dr_Tbl_Application[0]["id_connexion"]

只要Tbl_Application.id_connexion保持价值,一切都很好。如果此字段不包含值,我将收到以下错误:

InvalidCastException was unhandled

这些是我可以在即时窗口中看到的一些内容:

? dr_Programme[0]["id_Connexion"]
{}

? dr_Programme[0]["id_Connexion"].GetType()
{Name = "DBNull" FullName = "System.DBNull"}

? dr_Programme[0]["id_Connexion"] is System.DBNull
true

因此,为了避免我的异常,我想我最好在将唯一标识符值从数据库中的字段传输到局部变量之前进行测试。这就是说,我仍然对我的发现感到困扰,我想更深入地研究这个问题。

我的问题如下:

  1. 有没有办法编写一些基本代码来将数据库 Guid 值中的值分配给本地 Guid 对象而无需测试System.DBNull
  2. 为什么应用在同一个对象上的相同指令会返回不同的类型,这取决于原始字段是否包含值?

编辑问题2:

? dr_Programme[0]["id_Connexion"].GetType()

当对应的字段填充在原始表中时返回 System.Guid 类型,而

? dr_Programme[0]["id_Connexion"].GetType()

当原始表中的字段为空(或未填充)时,返回 System.DBNull 类型...

4

3 回答 3

4

DBNull实现Null 对象设计模式以解决DB 返回 NULL 与不返回任何内容之间的区别。不幸的是,缺乏直观性多年来一直困扰着程序员。

您能做的最好的事情就是将它包装在一个通用方法中,如下所示:

public static T? GetNullable<T>(object obj) where T : struct
{
    if (obj == DBNull.Value) return null;
    return (T?)obj;
}

现在你可以像这样调用这个方法:

mid_connexion = GetNullable<Guid>(dr_Tbl_Application[0]["id_connexion"]);
于 2012-12-28T12:58:12.380 回答
1

恐怕您将不得不继续检查 DBNull,除非您将数据库模式设计为​​不允许它们发生。另请注意,DBNull 与 C# null 不同。

通过使用 C# 中的 Convert 类,您可能可以使代码稍微不那么冗长。一般来说,它将执行默认转换而不是抛出异常(例如,当它遇到空值时;请注意,据我所知,它不知道如何处理 DBNull 值,因此您需要手动处理这些值)。

我的建议是创建一组扩展方法来完成必要的工作:

public static class AccessExtensions
{
    public static Guid GetGuidOrEmpty( this IDbReader reader, string columnName )
    {
        // all the code to check for DBNull and conversions goes here
        // ...

        return hasValue ? value : Guid.Empty;
    }
}

最后要注意的是,Access 对 GUID 可能很有趣,例如需要字符串进行插入/更新,但在选择时返回 GUID 类型。自从我在 2003 年左右尝试后,这可能已经有所改善。

于 2012-12-28T12:55:44.840 回答
1

用这个:

public static class SomeClass
    {
        public static Guid? With(this Guid? o, object x)
        {
            if (x is System.DBNull) return null;
            return o = (Guid)x;
        }
    }
于 2012-12-28T13:12:21.893 回答