1

我想用来自 MySql 数据库的数据初始化一个类。一些字段可以为空:

Dim dr As MySqlDataReader = ...
Dim item As New Item(dr.GetInt16(0), dr.GetString(1), dr.GetString(2))

假设数据库中的最后两个字段可能为 NULL,因此在该字段上调用 ​​GetString 会导致异常。

在获取每个字段之前,我当然可以编写代码来测试 NULL:

dim field1 as String 
if ( dr.IsDbNull(1) )
   field1 = Nothing                  ' or even ""
else
   field1 = dr.GetString(1)

但是,如果您有很多字段,这将是“如果”的噩梦。

为此,我重写了 IIf VB 函数以使其更具类型化,从而避免强制转换:

Namespace Util

Public Shared Function IIf(Of T)(ByVal condition As Boolean, ByVal iftrue As T, ByVal iffalse As T) As T
        If condition Then Return iftrue Else Return iffalse
End Function

这样我就可以写出类似的东西:

Dim item As New Item(
     dr.GetInt16(0), 
     Util.IIf(dr.IsDbNull(1), "", dr.GetString(1), 
     Util.IIf(dr.IsDbNull(2), "", dr.GetString(2))

类型化的IIf在其他情况下效果很好,但不幸的是在这种情况下它不是,因为它是一个普通函数而不是语言关键字,每个 inpout 参数都会在调用期间进行评估,并且当字段为 NULL 时引发异常.

你能想出一个优雅的 if-less 解决方案吗?

4

2 回答 2

0

首先,我建议您使用 ORM 映射器 - 如今您必须进行手动“映射”的情况很少。

如果这是其中一种情况,我建议您在访问 Data Reader 时使用字段名称而不是索引。

并回答您最初的问题:尝试扩展方法。对不起 C#,但 VB.NET 语法让我抓狂:

public static class DbDataReaderExtensions
{
    public static T GetField<T>(this DbDataReader dbDataReader, string fieldName, 
        T defaultValue)
    {
        if(dbDataReader.IsDBNull(fieldName))
            return defaultValue;
        return (T)dbDataReader[fieldName];
    }
}
于 2010-07-28T08:11:10.253 回答
0

谢谢。

我看过很多 ORM,但出于某种原因我不喜欢它们,所以我决定调用普通存储过程来获取数据。你能建议一些强大而简单的东西吗?

你是正确的使用字段名称,它更安全,即使有点慢。

我刚刚用这个方法得出了同样的结论,但我仍然不喜欢的是类型转换:

Public Shared Function IfNull(Of T)(ByVal dr As MySqlDataReader, ByVal index As Integer, ByVal _default As T) As T
        If dr.IsDBNull(index) Then
            Return _default
        Else
            Return CType(dr.GetValue(index), T)
        End If

End Function

我想做一些更优雅的事情来从读者那里获得“真实”的数据类型。

于 2010-07-28T09:11:19.840 回答