DataReader最佳实践

9

类似于这个问题,但回答从未真正回答我想知道的内容。 是否有关于从DataReader获取值的标准? 也就是说,这样做是否合适:

dataReader.GetString(dataReader.GetOrdinal("ColumnName"));

你是否认为这比/比这更差/一样好?
(string) dataReader["ColumnName"];
3个回答

11

这是我做的方法:

Int32 ordinal = dataReader.GetOrdinal("ColumnName");

if (!dataReader.IsDBNull(ordinal))
    yourString = dataReader.GetString(ordinal);

像我上面展示的那样检查 DBNull 是很重要的,因为如果 DataReader 中的字段为 null,则尝试检索它时会抛出异常。

需要检查 DBNull,否则在尝试检索一个为 null 的字段时将会抛出异常。


完全同意。我更多地是在询问获取实际值时使用DataReader的Item[]功能与使用提供的DataReader.Get<type value>方法之间的语法差异。 - AJ.
3
由于datareader["column"]返回的是一个对象而不是强类型,如果数据是DbNull,那么您不会立即得到异常,只会得到转换为对象的DbNull.Value。当然,如果您没有先执行Convert.IsDbNull检查,并尝试使用该值时,稍后可能会出现异常。 - Joel Mueller

9

我创建了一些扩展方法,让我将IDataReader作为可枚举对象来处理,并通过返回可空整数等方式处理DbNull。这使我可以使用C#的??运算符检查null并应用默认值。

/// <summary>
/// Returns an IEnumerable view of the data reader.
/// WARNING: Does not support readers with multiple result sets.
/// The reader will be closed after the first result set is read.
/// </summary>
public static IEnumerable<IDataRecord> AsEnumerable(this IDataReader reader)
{
    if (reader == null)
        throw new ArgumentNullException("reader");

    using (reader)
    {
        while (reader.Read())
        {
            yield return reader;
        }
    }
}

public static int? GetNullableInt32(this IDataRecord dr, string fieldName)
{
    return GetNullableInt32(dr, dr.GetOrdinal(fieldName));
}

public static int? GetNullableInt32(this IDataRecord dr, int ordinal)
{
    return dr.IsDBNull(ordinal) ? null : (int?)dr.GetInt32(ordinal);
}

还有其他关于IDataReaderGetDataType()方法,以此类推。


1
嗯,如果 IDataReaderIEnumerable 有任何关联的话,你是可以这样做的。然而,事实并非如此。接口的签名是:public interface IDataReader : IDisposable, IDataRecord - Joel Mueller
不错,但是在 while (reader.Read()) 循环之后你可能想要关闭阅读器。 - Ulf Lindback
嗯,读者真的从那个使用中关闭了吗?我以为只有在像这样在其中初始化读取器时,使用才会关闭读取器:using (var reader = new DataReader){...} 我错了吗? - SwissCoder
4
using语句只需要传入一个IDisposable实例,不一定要在括号内创建该实例。 - Joel Mueller
谢谢Joel抽出时间来,今天学到了新东西 :) - SwissCoder
@JoelMueller,DbDataReader 实现了 IEnumerable 接口,所以很少有人实现 IDataReader 而不从 DbDataReader 继承。因此基本上这样会起作用: ((DbDataReader)reader).Cast<IDataRecord>()。仅供参考。 - nawfal

0
这是一个扩展类;对我来说,它运行得相当不错。它处理了int和boolean的空值情况。
   public static class Utility
        {
            public static string ValidatorDataReaderString(this SqlDataReader pSqlDataReader, string pCampo)
            {
                var wValorReader = pSqlDataReader[pCampo];
                if (wValorReader != null)
                {
                    string wValorRetorno = Convert.ToString(pSqlDataReader[pCampo]);
                    return _ = wValorRetorno == string.Empty ? null : wValorRetorno;
                }
                else
                {
                    return null;
                }
            }
    
            public static int ValidatorDataReaderInt(this SqlDataReader pSqlDataReader, string pCampo)
            {
                var wValorReader = pSqlDataReader[pCampo];
                if (wValorReader != null)
                {
                    bool wValorParse = int.TryParse(Convert.ToString(pSqlDataReader[pCampo]), out int oValorRetorno);
                    return wValorParse ? oValorRetorno : 0;
                }
                else
                {
                    return 0;
                }
            }
    
            public static bool ValidatorDataReaderBool(this SqlDataReader pSqlDataReader, string pCampo)
            {
                if (pSqlDataReader[pCampo] != null)
                {
                    var wValor = Convert.ToString(pSqlDataReader[pCampo]);
    
                    if (wValor == "1" || wValor == "True")
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接