c#:如何将包含null值的guid类型的数据库字段强制转换为局部变量

本文关键字:字段 数据库 局部变量 转换 类型 guid 包含 值的 null | 更新日期: 2023-09-27 17:50:06

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

我通过DataRow[]数组dr_Tbl_Application从这个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()

返回系统。在原始表中填充相应字段时的Guid类型,而

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

返回系统。

c#:如何将包含null值的guid类型的数据库字段强制转换为局部变量

在原始表中字段为空(或未填充)时的DBNull类型。

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"]);

恐怕您将不得不继续检查DBNull,除非您设计的DB模式不允许它们发生。还要注意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年前后试用时有所改善。

使用

public static class SomeClass
    {
        public static Guid? With(this Guid? o, object x)
        {
            if (x is System.DBNull) return null;
            return o = (Guid)x;
        }
    }