SQL 数据读取器 - 处理空列值

发布于 2024-08-11 22:50:57 字数 202 浏览 7 评论 0原文

我正在使用 SQLdatareader 从数据库构建 POCO。除非在数据库中遇到空值,否则该代码将正常工作。例如,如果数据库中的 FirstName 列包含空值,则会引发异常。

employee.FirstName = sqlreader.GetString(indexFirstName);

在这种情况下我该如何处理空值?

I'm using a SQLdatareader to build POCOs from a database. The code works except when it encounters a null value in the database. For example, if the FirstName column in the database contains a null value, an exception is thrown.

employee.FirstName = sqlreader.GetString(indexFirstName);

How can I handle null values in this situation?

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

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

发布评论

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

评论(30

说谎友 2024-08-18 22:50:57

您需要检查 IsDBNull

if(!SqlReader.IsDBNull(indexFirstName))
{
  employee.FirstName = sqlreader.GetString(indexFirstName);
}

这是检测和处理这种情况的唯一可靠方法。

我将这些东西包装到扩展方法中,并且如果列确实为 null ,则倾向于返回默认值:

public static string SafeGetString(this SqlDataReader reader, int colIndex)
{
   if(!reader.IsDBNull(colIndex))
       return reader.GetString(colIndex);
   return string.Empty;
}

现在您可以这样调用它:

employee.FirstName = SqlReader.SafeGetString(indexFirstName);

并且您永远不必担心异常或 <再次使用 code>null 值。

You need to check for IsDBNull:

if(!SqlReader.IsDBNull(indexFirstName))
{
  employee.FirstName = sqlreader.GetString(indexFirstName);
}

That's your only reliable way to detect and handle this situation.

I wrapped those things into extension methods and tend to return a default value if the column is indeed null:

public static string SafeGetString(this SqlDataReader reader, int colIndex)
{
   if(!reader.IsDBNull(colIndex))
       return reader.GetString(colIndex);
   return string.Empty;
}

Now you can call it like this:

employee.FirstName = SqlReader.SafeGetString(indexFirstName);

and you'll never have to worry about an exception or a null value again.

青春有你 2024-08-18 22:50:57

您应该将 as 运算符与 ?? 运算符结合使用作为默认值。值类型需要被读取为可为空并给出默认值。

employee.FirstName = sqlreader[indexFirstName] as string;
employee.Age = sqlreader[indexAge] as int? ?? default(int);

as 运算符处理转换,包括检查 DBNull。

You should use the as operator combined with the ?? operator for default values. Value types will need to be read as nullable and given a default.

employee.FirstName = sqlreader[indexFirstName] as string;
employee.Age = sqlreader[indexAge] as int? ?? default(int);

The as operator handles the casting including the check for DBNull.

人│生佛魔见 2024-08-18 22:50:57
employee.FirstName = sqlreader[indexFirstName] as string;

对于整数,如果转换为可为 null 的 int,则可以使用 GetValueOrDefault()

employee.Age = (sqlreader[indexAge] as int?).GetValueOrDefault();

或 null 合并运算符 (??)。

employee.Age = (sqlreader[indexAge] as int?) ?? 0;
employee.FirstName = sqlreader[indexFirstName] as string;

For integers, if you cast to a nullable int, you can use GetValueOrDefault()

employee.Age = (sqlreader[indexAge] as int?).GetValueOrDefault();

or the null-coalescing operator (??).

employee.Age = (sqlreader[indexAge] as int?) ?? 0;
帅哥哥的热头脑 2024-08-18 22:50:57

IsDbNull(int) 通常比使用 GetSqlDateTime 等方法然后与 DBNull.Value 进行比较要慢得多。尝试 SqlDataReader 的这些扩展方法。

public static T Def<T>(this SqlDataReader r, int ord)
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return default(T);
    return ((INullable)t).IsNull ? default(T) : (T)t;
}

public static T? Val<T>(this SqlDataReader r, int ord) where T:struct
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return null;
    return ((INullable)t).IsNull ? (T?)null : (T)t;
}

public static T Ref<T>(this SqlDataReader r, int ord) where T : class
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return null;
    return ((INullable)t).IsNull ? null : (T)t;
}

像这样使用它们:

var dd = r.Val<DateTime>(ords[4]);
var ii = r.Def<int>(ords[0]);
int nn = r.Def<int>(ords[0]);

IsDbNull(int) is usually much slower than using methods like GetSqlDateTime and then comparing to DBNull.Value. Try these extension methods for SqlDataReader.

public static T Def<T>(this SqlDataReader r, int ord)
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return default(T);
    return ((INullable)t).IsNull ? default(T) : (T)t;
}

public static T? Val<T>(this SqlDataReader r, int ord) where T:struct
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return null;
    return ((INullable)t).IsNull ? (T?)null : (T)t;
}

public static T Ref<T>(this SqlDataReader r, int ord) where T : class
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return null;
    return ((INullable)t).IsNull ? null : (T)t;
}

Use them like this:

var dd = r.Val<DateTime>(ords[4]);
var ii = r.Def<int>(ords[0]);
int nn = r.Def<int>(ords[0]);
东风软 2024-08-18 22:50:57

if(reader.IsDBNull(ColumnIndex)) {//logic} 正如许多答案所述。

我想提一下,如果您使用列名,则仅比较类型可能会更舒服。

if(reader["TeacherImage"].GetType() == typeof(DBNull)) { //logic }

if(reader.IsDBNull(ColumnIndex)) {// logic} works as many answers says.

And I want to mention if you working with column names, just comparing types may be more comfortable.

if(reader["TeacherImage"].GetType() == typeof(DBNull)) { //logic }
过期以后 2024-08-18 22:50:57

当使用列名在数据读取器中返回行时,我认为不存在 NULL 列值。

如果你这样做 datareader["columnName"].ToString(); 它总是会给你一个可以是空字符串的值(String.Empty 如果你需要比较)。

我会使用以下内容并且不会太担心:

employee.FirstName = sqlreader["columnNameForFirstName"].ToString();

I don't think there's a NULL column value, when rows are returned within a datareader using the column name.

If you do datareader["columnName"].ToString(); it will always give you a value that can be a empty string (String.Empty if you need to compare).

I would use the following and wouldn't worry too much:

employee.FirstName = sqlreader["columnNameForFirstName"].ToString();
奶气 2024-08-18 22:50:57

您可以编写一个通用函数来检查 Null 并在它为 NULL 时包含默认值。读取Datareader时调用此方法

public T CheckNull<T>(object obj)
        {
            return (obj == DBNull.Value ? default(T) : (T)obj);
        }

读取Datareader时使用

                        while (dr.Read())
                        {
                            tblBPN_InTrRecon Bpn = new tblBPN_InTrRecon();
                            Bpn.BPN_Date = CheckNull<DateTime?>(dr["BPN_Date"]);
                            Bpn.Cust_Backorder_Qty = CheckNull<int?>(dr["Cust_Backorder_Qty"]);
                            Bpn.Cust_Min = CheckNull<int?>(dr["Cust_Min"]);
                         }

You can write a Generic function to check Null and include default value when it is NULL. Call this when reading Datareader

public T CheckNull<T>(object obj)
        {
            return (obj == DBNull.Value ? default(T) : (T)obj);
        }

When reading the Datareader use

                        while (dr.Read())
                        {
                            tblBPN_InTrRecon Bpn = new tblBPN_InTrRecon();
                            Bpn.BPN_Date = CheckNull<DateTime?>(dr["BPN_Date"]);
                            Bpn.Cust_Backorder_Qty = CheckNull<int?>(dr["Cust_Backorder_Qty"]);
                            Bpn.Cust_Min = CheckNull<int?>(dr["Cust_Min"]);
                         }
绮烟 2024-08-18 22:50:57

一种方法是检查数据库空值:

employee.FirstName = (sqlreader.IsDBNull(indexFirstName) 
    ? ""
    : sqlreader.GetString(indexFirstName));

One way to do it is to check for db nulls:

employee.FirstName = (sqlreader.IsDBNull(indexFirstName) 
    ? ""
    : sqlreader.GetString(indexFirstName));
暖树树初阳… 2024-08-18 22:50:57

该解决方案对供应商的依赖性较小,并且可与 SQL、OleDB 和 MySQL Reader 配合使用:

public static string GetStringSafe(this IDataReader reader, int colIndex)
{
    return GetStringSafe(reader, colIndex, string.Empty);
}

public static string GetStringSafe(this IDataReader reader, int colIndex, string defaultValue)
{
    if (!reader.IsDBNull(colIndex))
        return reader.GetString(colIndex);
    else
        return defaultValue;
}

public static string GetStringSafe(this IDataReader reader, string indexName)
{
    return GetStringSafe(reader, reader.GetOrdinal(indexName));
}

public static string GetStringSafe(this IDataReader reader, string indexName, string defaultValue)
{
    return GetStringSafe(reader, reader.GetOrdinal(indexName), defaultValue);
}

This Solution is less vendor-dependent and works with an SQL, OleDB, and MySQL Reader:

public static string GetStringSafe(this IDataReader reader, int colIndex)
{
    return GetStringSafe(reader, colIndex, string.Empty);
}

public static string GetStringSafe(this IDataReader reader, int colIndex, string defaultValue)
{
    if (!reader.IsDBNull(colIndex))
        return reader.GetString(colIndex);
    else
        return defaultValue;
}

public static string GetStringSafe(this IDataReader reader, string indexName)
{
    return GetStringSafe(reader, reader.GetOrdinal(indexName));
}

public static string GetStringSafe(this IDataReader reader, string indexName, string defaultValue)
{
    return GetStringSafe(reader, reader.GetOrdinal(indexName), defaultValue);
}
最佳男配角 2024-08-18 22:50:57

通过 getpsyched 的答案的影响,我创建了一个通用方法,通过名称检查列值

public static T SafeGet<T>(this System.Data.SqlClient.SqlDataReader reader, string nameOfColumn)
{
  var indexOfColumn = reader.GetOrdinal(nameOfColumn);
  return reader.IsDBNull(indexOfColumn) ? default(T) : reader.GetFieldValue<T>(indexOfColumn);
}

用法:

var myVariable = SafeGet<string>(reader, "NameOfColumn")

By influencing from getpsyched's answer, I created a generic method which checks column value by its name

public static T SafeGet<T>(this System.Data.SqlClient.SqlDataReader reader, string nameOfColumn)
{
  var indexOfColumn = reader.GetOrdinal(nameOfColumn);
  return reader.IsDBNull(indexOfColumn) ? default(T) : reader.GetFieldValue<T>(indexOfColumn);
}

Usage:

var myVariable = SafeGet<string>(reader, "NameOfColumn")
百思不得你姐 2024-08-18 22:50:57

我倾向于做的是将 SELECT 语句中的空值替换为适当的值。

SELECT ISNULL(firstname, '') FROM people

在这里,我将每个 null 替换为空白字符串。在这种情况下,您的代码不会抛出错误。

What I tend to do is replace the null values in the SELECT statement with something appropriate.

SELECT ISNULL(firstname, '') FROM people

Here I replace every null with a blank string. Your code won't throw in error in that case.

绝不放开 2024-08-18 22:50:57

在尝试读取之前请检查sqlreader.IsDBNull(indexFirstName)

Check sqlreader.IsDBNull(indexFirstName) before you try to read it.

蓝咒 2024-08-18 22:50:57

作为 marc_s 答案的补充,您可以使用更通用的扩展方法从 SqlDataReader 获取值:

public static T SafeGet<T>(this SqlDataReader reader, int col)
    {
        return reader.IsDBNull(col) ? default(T) : reader.GetFieldValue<T>(col);
    }

As an addition to the answer by marc_s, you can use a more generic extension method to get values from the SqlDataReader:

public static T SafeGet<T>(this SqlDataReader reader, int col)
    {
        return reader.IsDBNull(col) ? default(T) : reader.GetFieldValue<T>(col);
    }
如此安好 2024-08-18 22:50:57

我想你会想使用:

SqlReader.IsDBNull(indexFirstName)

I think you would want to use:

SqlReader.IsDBNull(indexFirstName)
噩梦成真你也成魔 2024-08-18 22:50:57

如何创建辅助方法

对于字符串

private static string MyStringConverter(object o)
    {
        if (o == DBNull.Value || o == null)
            return "";

        return o.ToString();
    }

用法

MyStringConverter(read["indexStringValue"])

对于 Int

 private static int MyIntonverter(object o)
    {
        if (o == DBNull.Value || o == null)
            return 0;

        return Convert.ToInt32(o);
    }

用法

MyIntonverter(read["indexIntValue"])

对于日期

private static DateTime? MyDateConverter(object o)
    {
        return (o == DBNull.Value || o == null) ? (DateTime?)null : Convert.ToDateTime(o);
    }

用法

MyDateConverter(read["indexDateValue"])

注意:对于 DateTime,将变量声明为

DateTime? variable;

how to about creating helper methods

For String

private static string MyStringConverter(object o)
    {
        if (o == DBNull.Value || o == null)
            return "";

        return o.ToString();
    }

Usage

MyStringConverter(read["indexStringValue"])

For Int

 private static int MyIntonverter(object o)
    {
        if (o == DBNull.Value || o == null)
            return 0;

        return Convert.ToInt32(o);
    }

Usage

MyIntonverter(read["indexIntValue"])

For Date

private static DateTime? MyDateConverter(object o)
    {
        return (o == DBNull.Value || o == null) ? (DateTime?)null : Convert.ToDateTime(o);
    }

Usage

MyDateConverter(read["indexDateValue"])

Note: for DateTime declare varialbe as

DateTime? variable;
月下客 2024-08-18 22:50:57

这些都不是我想要的:

 public static T GetFieldValueOrDefault<T>(this SqlDataReader reader, string name)
 {
     int index = reader.GetOrdinal(name);
     T value = reader.IsDBNull(index) ? default(T) : reader.GetFieldValue<T>(index);
     return value;
 }

None of these was quite what i wanted:

 public static T GetFieldValueOrDefault<T>(this SqlDataReader reader, string name)
 {
     int index = reader.GetOrdinal(name);
     T value = reader.IsDBNull(index) ? default(T) : reader.GetFieldValue<T>(index);
     return value;
 }
抹茶夏天i‖ 2024-08-18 22:50:57

这里有很多答案,其中传播着有用的信息(以及一些错误的信息),我想将它们放在一起。

这个问题的简短答案是检查 DBNull - 几乎每个人都同意这一点:)

通用方法允许我们用更少的代码来解决这个问题,而不是使用辅助方法来读取每个 SQL 数据类型的可为空值。但是,您不能为可为空值类型和引用类型提供单一泛型方法,这将在
可以为空类型作为泛型参数吗? 和 < a href="https://stackoverflow.com/questions/19831157/c-sharp-generic-type-constraint-for-everything-nullable">针对所有可为 null 的内容的 C# 泛型类型约束。

因此,根据 @ZXX 和 @getpsyched 的答案,我们最终得到了两种获取可为空值的方法,并且我添加了第三种用于非空值的方法(它根据方法命名完成了集合)。

public static T? GetNullableValueType<T>(this SqlDataReader sqlDataReader, string columnName) where T : struct
{
    int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
    return sqlDataReader.IsDBNull(columnOrdinal) ? (T?)null : sqlDataReader.GetFieldValue<T>(columnOrdinal);
}

public static T GetNullableReferenceType<T>(this SqlDataReader sqlDataReader, string columnName) where T : class
{
    int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
    return sqlDataReader.IsDBNull(columnOrdinal) ? null : sqlDataReader.GetFieldValue<T>(columnOrdinal);
}

public static T GetNonNullValue<T>(this SqlDataReader sqlDataReader, string columnName)
{
    int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
    return sqlDataReader.GetFieldValue<T>(columnOrdinal);
}

我通常使用列名称,如果您使用列索引,请更改这些名称。根据这些方法名称,我可以判断数据是否可以为空,这在查看很久以前编写的代码时非常有用。

尖端;

  • 数据库中没有可为空的列可以避免此问题。如果你
    可以控制数据库,那么列应该是非空的
    默认且仅在必要时可为空。
  • 不要转换数据库值
    使用 C# 'as' 运算符,因为如果转换错误,它将
    默默返回null。
  • 使用默认值表达式将会改变
    数据库将 null 值转换为 int、datetime 等值类型的非空值
    最后,在对所有 SQL Server 数据类型测试上述方法时,

我发现您无法直接从 SqlDataReader 获取 char[],如果您想要 char[],则必须获取字符串并使用 ToCharArray( )。

There are a lot of answers here with useful info (and some wrong info) spread about, I'd like to bring it all together.

The short answer to the question is to check for DBNull - almost everyone agrees on this bit :)

Rather than using a helper method to read nullable values per SQL data type a generic method allows us to address this with a lot less code. However, you can't have a single generic method for both nullable value types and reference types, this is discussed at length in
Nullable type as a generic parameter possible? and C# generic type constraint for everything nullable.

So, following on from the answers from @ZXX and @getpsyched we end up with this, 2 methods for getting nullable values and I've added a 3rd for non-null values (it completes the set based on method naming).

public static T? GetNullableValueType<T>(this SqlDataReader sqlDataReader, string columnName) where T : struct
{
    int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
    return sqlDataReader.IsDBNull(columnOrdinal) ? (T?)null : sqlDataReader.GetFieldValue<T>(columnOrdinal);
}

public static T GetNullableReferenceType<T>(this SqlDataReader sqlDataReader, string columnName) where T : class
{
    int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
    return sqlDataReader.IsDBNull(columnOrdinal) ? null : sqlDataReader.GetFieldValue<T>(columnOrdinal);
}

public static T GetNonNullValue<T>(this SqlDataReader sqlDataReader, string columnName)
{
    int columnOrdinal = sqlDataReader.GetOrdinal(columnName);
    return sqlDataReader.GetFieldValue<T>(columnOrdinal);
}

I usually use column names, alter these if you use column indexes. Based on these method names I can tell whether I'm expecting the data to be nullable or not, quite useful when looking at code written a long time ago.

Tips;

  • Not having nullable columns in the database avoids this issue. If you
    have control over the database then columns should be non-null by
    default and only nullable where necessary.
  • Don't cast database values
    with the C# 'as' operator because if the cast is wrong it will
    silently return null.
  • Using a default value expression will change
    database nulls to non-null values for value types like int, datetime,
    bit etc.

Lastly, whilst testing the above methods across all SQL Server data types I discovered you can't directly get a char[] from a SqlDataReader, if you want a char[] you will have to get a string and use ToCharArray().

月光色 2024-08-18 22:50:57

我们使用一系列静态方法从数据读取器中提取所有值。因此,在这种情况下,我们将调用 DBUtils.GetString(sqlreader(indexFirstName)) 创建静态/共享方法的好处是,您不必一遍又一遍地执行相同的检查...

静态方法将包含检查空值的代码(请参阅本页上的其他答案)。

We use a series of static methods to pull all of the values out of our data readers. So in this case we'd be calling DBUtils.GetString(sqlreader(indexFirstName)) The benefit of creating static/shared methods is that you don't have to do the same checks over and over and over...

The static method(s) would contain code to check for nulls (see other answers on this page).

赤濁 2024-08-18 22:50:57

您可以使用条件运算符:

employee.FirstName = sqlreader["indexFirstName"] != DBNull.Value ? sqlreader[indexFirstName].ToString() : "";

You may use the conditional operator:

employee.FirstName = sqlreader["indexFirstName"] != DBNull.Value ? sqlreader[indexFirstName].ToString() : "";
恋你朝朝暮暮 2024-08-18 22:50:57

这是辅助类,其他人可以根据 @marc_s 的回答使用它们:

public static class SQLDataReaderExtensions
    {
        public static int SafeGetInt(this SqlDataReader dataReader, string fieldName)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.IsDBNull(fieldIndex) ? 0 : dataReader.GetInt32(fieldIndex);
        }

        public static int? SafeGetNullableInt(this SqlDataReader dataReader, string fieldName)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.GetValue(fieldIndex) as int?;
        }

        public static string SafeGetString(this SqlDataReader dataReader, string fieldName)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.IsDBNull(fieldIndex) ? string.Empty : dataReader.GetString(fieldIndex);
        }

        public static DateTime? SafeGetNullableDateTime(this SqlDataReader dataReader, string fieldName)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.GetValue(fieldIndex) as DateTime?;
        }

        public static bool SafeGetBoolean(this SqlDataReader dataReader, string fieldName)
        {
            return SafeGetBoolean(dataReader, fieldName, false);
        }

        public static bool SafeGetBoolean(this SqlDataReader dataReader, string fieldName, bool defaultValue)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.IsDBNull(fieldIndex) ? defaultValue : dataReader.GetBoolean(fieldIndex);
        }
    }

Here is helper class which others can use if they need based on @marc_s answer:

public static class SQLDataReaderExtensions
    {
        public static int SafeGetInt(this SqlDataReader dataReader, string fieldName)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.IsDBNull(fieldIndex) ? 0 : dataReader.GetInt32(fieldIndex);
        }

        public static int? SafeGetNullableInt(this SqlDataReader dataReader, string fieldName)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.GetValue(fieldIndex) as int?;
        }

        public static string SafeGetString(this SqlDataReader dataReader, string fieldName)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.IsDBNull(fieldIndex) ? string.Empty : dataReader.GetString(fieldIndex);
        }

        public static DateTime? SafeGetNullableDateTime(this SqlDataReader dataReader, string fieldName)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.GetValue(fieldIndex) as DateTime?;
        }

        public static bool SafeGetBoolean(this SqlDataReader dataReader, string fieldName)
        {
            return SafeGetBoolean(dataReader, fieldName, false);
        }

        public static bool SafeGetBoolean(this SqlDataReader dataReader, string fieldName, bool defaultValue)
        {
            int fieldIndex = dataReader.GetOrdinal(fieldName);
            return dataReader.IsDBNull(fieldIndex) ? defaultValue : dataReader.GetBoolean(fieldIndex);
        }
    }
花开雨落又逢春i 2024-08-18 22:50:57

在 c# 7.0 中我们可以这样做:

var a = reader["ERateCode"] as string;
var b = reader["ERateLift"] as int?;
var c = reader["Id"] as int?;

所以如果是的话它将保留 null 值。

in c# 7.0 we can do :

var a = reader["ERateCode"] as string;
var b = reader["ERateLift"] as int?;
var c = reader["Id"] as int?;

so it will keep null value if it is.

﹂绝世的画 2024-08-18 22:50:57

我尽力从 DataTable 重新实现 Field 方法。 https://learn.microsoft.com/en- us/dotnet/api/system.data.datarowextensions.field

如果您尝试将 DBNull.Value 转换为不可空类型,则会抛出异常。否则,它将把 DBNull.Value 转换为 null

我还没有完全测试过。

public static T Field<T>(this SqlDataReader sqlDataReader, string columnName)
{
    int columnIndex = sqlDataReader.GetOrdinal(columnName);
    if (sqlDataReader.IsDBNull(columnIndex))
    {
        if (default(T) != null)
        {
            throw new InvalidCastException("Cannot convert DBNULL value to type " + typeof(T).Name);
        }
        else
        {
            return default(T);
        }
    }
    else
    {
        return sqlDataReader.GetFieldValue<T>(columnIndex);
    }
}

用法:

string fname = sqlDataReader.Field<string>("FirstName");
int? age = sqlDataReader.Field<int?>("Age");
int yearsOfExperience = sqlDataReader.Field<int?>("YearsEx") ?? 0;

I did my best to reimplement the Field method from DataTable. https://learn.microsoft.com/en-us/dotnet/api/system.data.datarowextensions.field

It will throw if you try to convert a DBNull.Value to a non-nullable type. Otherwise it will convert DBNull.Value to null.

I haven't fully tested it.

public static T Field<T>(this SqlDataReader sqlDataReader, string columnName)
{
    int columnIndex = sqlDataReader.GetOrdinal(columnName);
    if (sqlDataReader.IsDBNull(columnIndex))
    {
        if (default(T) != null)
        {
            throw new InvalidCastException("Cannot convert DBNULL value to type " + typeof(T).Name);
        }
        else
        {
            return default(T);
        }
    }
    else
    {
        return sqlDataReader.GetFieldValue<T>(columnIndex);
    }
}

Usage:

string fname = sqlDataReader.Field<string>("FirstName");
int? age = sqlDataReader.Field<int?>("Age");
int yearsOfExperience = sqlDataReader.Field<int?>("YearsEx") ?? 0;
一瞬间的火花 2024-08-18 22:50:57

我使用下面列出的代码来处理读入数据表的 Excel 工作表中的空单元格。

if (!reader.IsDBNull(2))
{
   row["Oracle"] = (string)reader[2];
}

I am using the code listed below to handle null cells in an Excel sheet that is read in to a datatable.

if (!reader.IsDBNull(2))
{
   row["Oracle"] = (string)reader[2];
}
猫七 2024-08-18 22:50:57
private static void Render(IList<ListData> list, IDataReader reader)
        {
            while (reader.Read())
            {

                listData.DownUrl = (reader.GetSchemaTable().Columns["DownUrl"] != null) ? Convert.ToString(reader["DownUrl"]) : null;
                //没有这一列时,让其等于null
                list.Add(listData);
            }
            reader.Close();
        }
private static void Render(IList<ListData> list, IDataReader reader)
        {
            while (reader.Read())
            {

                listData.DownUrl = (reader.GetSchemaTable().Columns["DownUrl"] != null) ? Convert.ToString(reader["DownUrl"]) : null;
                //没有这一列时,让其等于null
                list.Add(listData);
            }
            reader.Close();
        }
你另情深 2024-08-18 22:50:57

和/或使用三元运算符进行赋值:

employee.FirstName = rdr.IsDBNull(indexFirstName))? 
                     String.Empty: rdr.GetString(indexFirstName);

根据每个属性类型替换默认值(当为空时)...

and / or use ternary operator with assignment:

employee.FirstName = rdr.IsDBNull(indexFirstName))? 
                     String.Empty: rdr.GetString(indexFirstName);

replace the default (when null) value as appropriate for each property type...

寄离 2024-08-18 22:50:57

此方法依赖于indexFirstName,它应该是从零开始的列序数。

if(!sqlReader.IsDBNull(indexFirstName))
{
  employee.FirstName = sqlreader.GetString(indexFirstName);
}

如果您不知道列索引但不想检查名称,您可以使用此扩展方法:

public static class DataRecordExtensions
{
    public static bool HasColumn(this IDataRecord dr, string columnName)
    {
        for (int i=0; i < dr.FieldCount; i++)
        {
            if (dr.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase))
                return true;
        }
        return false;
    }
}

并使用如下方法:

if(sqlReader.HasColumn("FirstName"))
{
  employee.FirstName = sqlreader["FirstName"];
}

This method is dependent on indexFirstName which should be the zero-based column ordinal.

if(!sqlReader.IsDBNull(indexFirstName))
{
  employee.FirstName = sqlreader.GetString(indexFirstName);
}

If you don't know the column index but wan't to check a name you can use this extension method instead:

public static class DataRecordExtensions
{
    public static bool HasColumn(this IDataRecord dr, string columnName)
    {
        for (int i=0; i < dr.FieldCount; i++)
        {
            if (dr.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase))
                return true;
        }
        return false;
    }
}

And use the method like this:

if(sqlReader.HasColumn("FirstName"))
{
  employee.FirstName = sqlreader["FirstName"];
}
月寒剑心 2024-08-18 22:50:57

老问题,但也许有人仍然需要真正的答案,

我像这样解决了这个问题

对于 int :

public static object GatDataInt(string Query, string Column)
    {
        SqlConnection DBConn = new SqlConnection(ConnectionString);
        if (DBConn.State == ConnectionState.Closed)
            DBConn.Open();
        SqlCommand CMD = new SqlCommand(Query, DBConn);
        SqlDataReader RDR = CMD.ExecuteReader();
        if (RDR.Read())
        {
            var Result = RDR[Column];
            RDR.Close();
            DBConn.Close();
            return Result;
        }
        return 0;
    }

对于字符串相同,只需返回“”而不是 0,因为“”是空字符串,

所以你可以像使用它一样

int TotalPoints = GatDataInt(QueryToGetTotalPoints, TotalPointColumn) as int?;

并且

string Email = GatDatastring(QueryToGetEmail, EmailColumn) as string;

非常灵活,所以你可以插入任何查询来读取任何列,它永远不会返回错误

Old question but maybe someone still need an answer

in real i worked around this issue like that

For int :

public static object GatDataInt(string Query, string Column)
    {
        SqlConnection DBConn = new SqlConnection(ConnectionString);
        if (DBConn.State == ConnectionState.Closed)
            DBConn.Open();
        SqlCommand CMD = new SqlCommand(Query, DBConn);
        SqlDataReader RDR = CMD.ExecuteReader();
        if (RDR.Read())
        {
            var Result = RDR[Column];
            RDR.Close();
            DBConn.Close();
            return Result;
        }
        return 0;
    }

the same for string just return "" instead of 0 as "" is empty string

so you can use it like

int TotalPoints = GatDataInt(QueryToGetTotalPoints, TotalPointColumn) as int?;

and

string Email = GatDatastring(QueryToGetEmail, EmailColumn) as string;

very flexible so you can insert any query to read any column and it'll never return with error

晚风撩人 2024-08-18 22:50:57

整齐的一行:

    while (dataReader.Read())
{
    employee.FirstName = (!dataReader.IsDBNull(dataReader.GetOrdinal("FirstName"))) ? dataReader["FirstName"].ToString() : "";
}

neat one-liner:

    while (dataReader.Read())
{
    employee.FirstName = (!dataReader.IsDBNull(dataReader.GetOrdinal("FirstName"))) ? dataReader["FirstName"].ToString() : "";
}
辞取 2024-08-18 22:50:57

合理地转换句柄 DbNull。

employee.FirstName = Convert.ToString(sqlreader.GetValue(indexFirstName));

Convert handles DbNull sensibly.

employee.FirstName = Convert.ToString(sqlreader.GetValue(indexFirstName));
予囚 2024-08-18 22:50:57

你也可以检查一下

if(null !=x && x.HasRows)
{ ....}

you can ever check for this as well

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