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

C#:如何将包含空值的guid类型的数据库字段强制转换为局部变量?,c#,ms-access,guid,C#,Ms Access,Guid,我有一个Access数据库,其中Tbl\u Application.id\u connexion是一个带有Guid类型的字段(在ms Access术语中称为“复制id”) 我正在通过DataRow[]数组,dr\u Tbl\u应用程序从这个Tbl\u应用程序表收集一些数据。以下代码读取第一个数据行: private Guid? mid_connexion = null; mid_connexion = (Guid)dr_Tbl_Application[0]["id_connexion"] 只要

我有一个Access数据库,其中
Tbl\u Application.id\u connexion
是一个带有
Guid
类型的字段(在ms Access术语中称为“复制id”)

我正在通过
DataRow[]
数组,
dr\u Tbl\u应用程序
从这个Tbl\u应用程序表收集一些数据。以下代码读取第一个数据行:

private Guid? mid_connexion = null;
mid_connexion = (Guid)dr_Tbl_Application[0]["id_connexion"]
只要
Tbl\u Application.id\u 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
所以,为了避免我的异常,我想我最好在将唯一标识符值从数据库中的字段传输到局部变量之前进行测试。尽管如此,我仍然对我的发现感到困扰,我想更深入地探讨这个问题

我的问题如下:

  • 有没有一种方法可以编写一些基本代码,将数据库Guid值中的值分配给本地Guid对象,而无需在
    System.DBNull
    上进行测试
  • 为什么应用于同一对象的同一条指令会返回不同的类型,这取决于原始字段是否包含值 编辑问题2:

    ? dr_Programme[0]["id_Connexion"].GetType()
    
    在原始表中填充相应字段时返回System.Guid类型,而

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

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

    恐怕您必须继续检查DBNull,除非您将DB架构设计为不允许出现DBNull。还要注意,DBNull不同于C#null

    通过在C#中使用Convert类,您可能会使代码稍微不那么冗长。通常,它将执行默认转换,而不是抛出异常(例如,当它遇到null值时;请注意,据我所知,它不知道如何处理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;
        }
    }
    

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

    DBNull
    实现了to地址。不幸的是,它缺乏直观性多年来一直让程序员们感到困惑

    您所能做的最好是将其包装在通用方法中,如下所示:

    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"]);
    
    publicstatict?GetNullable(objectobj),其中T:struct
    {
    if(obj==DBNull.Value)返回null;
    返回(T?)obj;
    }
    
    现在可以这样调用此方法:

    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"]);
    
    mid_connexion=GetNullable(dr_Tbl_应用程序[0][“id_connexion”]);
    
    使用以下方法:

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

    您是否尝试过
    mid\u connexion=(Guid?)dr\u Tbl\u应用程序[0][“id\u connexion”]
    请注意以下问题?将其标记为可为空的Guid,就像使用mid_连接时所做的那样。因为
    (Guid)dr\u Tbl\u应用程序[0][“id\u connexion”]
    将尝试将null强制转换为一种不可为null的Guid类型。@Syneryx不起作用。System.DBNull不能转换为Nullable。@HamletHakobyan我的错。但似乎Morten mertner有一个答案。这已经在Access表和Access vba之间的Guid管理中讨论过了,\或者其他vb代码一直是一个真正的PITA。。。