c# - 单一方法,可以返回数据行中某列的值,并自动处理该列可能为空的情况

标签 c# generics

任何人都可以建议一个单一的方法,它可以返回数据行中列的值并自动处理列值可能为 null 的可能性。本质上,我试图想出一个通用的解决方案,利用 DataRow 扩展方法来处理 DBNull 值。到目前为止,我的解决方案是:

public static Nullable<T> SafeRead<T>(DataRow row, string fieldName) where T : struct
{
    if (row.HasColumn(fieldName))
    {
        return row.Field<Nullable<T>>(fieldName) ?? default(Nullable<T>);
    }
    else
        return default(Nullable<T>);
}

public static T SafeRead<T>(DataRow row, string fieldName) where T : class
{
    if (row.HasColumn(fieldName))
    {
        return row.Field<T>(fieldName) ?? default(T);
    }
    else
        return default(T);
}

但这显然是在提示方法歧义,因为 C# 不允许基于参数约束的方法重载

最佳答案

以下将为您提供从数据行返回的值,或者如果值为 DBNull.Value 则返回类型的默认值。如果未定义该字段,它将抛出 ArgumentException。

using System;
using System.Data;

public static class DataAccess
{
    public static T GetValueOrDefault<T>(DataRow row, string fieldName)
    {
        if (!row.Table.Columns.Contains(fieldName))
        {
            throw new ArgumentException(
                string.Format("The given DataRow does not contain a field with the name \"{0}\".", fieldName));
        }
        else if (row[fieldName].Equals(DBNull.Value))
        {
            return default(T);
        }

        return row.Field<T>(fieldName);
    }
}

这里有一些简单的测试:

[TestMethod]
public void GetValueOrDefault_ValueType_Test()
{
    const string FieldName = "Column";
    const int Expected = 5;

    DataTable dataTable = new DataTable();
    dataTable.Columns.Add(FieldName, typeof(int));

    DataRow row = dataTable.Rows.Add(Expected);

    int actual = DataAccess.GetValueOrDefault<int>(row, FieldName);
    Assert.AreEqual(Expected, actual);
}

[TestMethod]
public void GetValueOrDefault_ValueType_DBNull_Test()
{
    const string FieldName = "Column";

    DataTable dataTable = new DataTable();
    dataTable.Columns.Add(FieldName, typeof(int));

    DataRow row = dataTable.Rows.Add(DBNull.Value);

    int actual = DataAccess.GetValueOrDefault<int>(row, FieldName);
    Assert.AreEqual(default(int), actual);
}

[TestMethod]
public void GetValueOrDefault_ReferenceType_Test()
{
    const string FieldName = "Column";
    object expected = new object();

    DataTable dataTable = new DataTable();
    dataTable.Columns.Add(FieldName, typeof(object));

    DataRow row = dataTable.Rows.Add(expected);

    object actual = DataAccess.GetValueOrDefault<object>(row, FieldName);
    Assert.AreEqual(expected, actual);
}

[TestMethod]
public void GetValueOrDefault_ReferenceType_DBNull_Test()
{
    const string FieldName = "Column";

    DataTable dataTable = new DataTable();
    dataTable.Columns.Add(FieldName, typeof(object));

    DataRow row = dataTable.Rows.Add(DBNull.Value);

    object actual = DataAccess.GetValueOrDefault<object>(row, FieldName);
    Assert.AreEqual(default(object), actual);
}

关于c# - 单一方法,可以返回数据行中某列的值,并自动处理该列可能为空的情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10214155/

相关文章:

c# - 具有重复行标题和换行的 RDLC

c# - 是否可以从 Object 参数中排除 IEnumerable 和原始类型?

c# - 为什么 IEnumerable<T> 不实现 Add(T)?

c# - 如何使用最小起订量模拟 ReadOnlyCollection<T> 属性

c# - Lambda Func<> 和 Fluent

即使参数为零,也需要 Swift 可选泛型类型

具有泛型参数基础的 Java 泛型参数

c# - 具有通用类层次结构的 Protobuf 属性

c# - 尝试在进程退出时运行代码 C#

c# - 查找 Lat Long 位置是否在 esri shapefile 中的形状中