VB.NET 2010 和 MySql - 为懒人处理 DB NULL

发布于 2024-09-11 22:14:33 字数 1078 浏览 2 评论 0原文

我想用来自 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)

但是如果您有很多字段,那么这就是一场“ifs”噩梦。

为此,我重写了 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 在其他情况下工作良好,但不幸的是它并不在这种情况下,因为它是一个普通函数而不是语言关键字,所以每个输入参数都会在调用期间进行评估,并且当该字段为 NULL 时会引发异常。

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

I want to initialize a class with data coming from a MySql db. Some fields can be null:

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

Suppose the last two fields could be NULL In the db, so that calling GetString on that field causes an exception.

I could certainly write code to test for NULLs before I get each field:

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

But if you have many fields this is an "ifs" nightmare.

To this purpose I rewrote the IIf VB function to make it more typed, thus to avoid casts:

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

So that I could write something like:

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

The typed IIf works well in other cases, but unfortunately it doesn't in this instance, because being it a normal function and not a language keyword, each inpout parameter is evaluated during the call, and when the field is NULL the exception is raised.

Can you think of an elegant if-less solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吐个泡泡 2024-09-18 22:14:33

首先,我建议您使用 ORM 映射器 - 现在很少有情况需要您进行手动“映射”。

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

并回答您原来的问题:尝试扩展方法。对 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];
    }
}

First off, I'd recommend you to use an ORM mapper - there are very few cases nowadays when you have to do manual "mapping".

If this is one of these cases, I'd recommend you to use field names instead of indexes while accessing Data Reader.

And to answer your original question: try extension methods. Sorry for C#, but VB.NET syntax drives me nuts:

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];
    }
}
甜尕妞 2024-09-18 22:14:33

谢谢。

我看过很多 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

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

Thanks.

I have looked at many ORMs and I don't like them for one reason or another, so I decided to call plain stored procedures to get data. Can you advice something powerful yet simple?

You're right about to use field names, it is safer, even if a little bit slower.

I had just arrived to the same conclusion with the method, but what I still don't like is the type conversion:

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

I would like to do something more elegant to get the "real" data type from the reader.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文