寻找从DataRow读取列并将其设置为变量的泛型函数



我有一个装载了SQL视图数据的DataRow。然后我读取DataRow的列,并将它们分配给一个对象,该对象的属性实际上是sql视图的列名。我们的目标是拥有一个动态返回列值的泛型函数。但是,如果传递的值是数值而不是alphannumeric,那么似乎该值被解释为Int32而不是String。异常如下:无法强制转换"System"类型的对象。

输入"System.String"。这是调用函数:

foreach (DataRow dr in dt)
{
    MyObject myObject = new MyObject(dr);
    //Continue with myObject
}

在MyObject的构造函数中,我试图读取DataRow的值并将它们设置为对象的属性。我尝试了以下

public MyObject(DataRow dr)
 {
     _comments = Utils.GetDbValue<string>(dr, "comments"); //fails if "comments" == "1"
     _comments = Utils.GetDbString(dr, "comments"); //fails if "comments" == "1"
     _comments = dr.Field<string>("comments"); //fails if "comments" == "1"
 }

_comments是MyObject的私有字段,而"comments"是列名。如果"comments"正确填写(就像一个实际的字符串),那么我就没有任何问题。如果值是整数(例如'1'),则将其解释为Int32并抛出强制转换异常。

public static class Utils
{
    public static T GetDbValue<T>(DataRow dataRow, string columnName)
    {
        int index = dataRow.Table.Columns.IndexOf(columnName);
    if (index < 0 || index > dataRow.ItemArray.Count())
    {
        return default(T);
    }
    else
    {
        return (T)dataRow[index];
    }
    }
    //Cannot be used for other data types (i.e Int, DateTime)
    public static string GetDBString(DataRow dataRow, string columnName)
    {
        if (dataRow.IsNull(columnName))
    {
        return string.Empty;
    }
    else
    {
        return dataRow.Field<string>(columnName);
    }
    }
}

编辑:

到目前为止,这个函数似乎工作得很好,尽管它没有测试,但对于Integer, String, DateTime和Decimal类型

        public static T GetDbValue<T>(DataRow dataRow, string columnName)
        {
            int index = dataRow.Table.Columns.IndexOf(columnName);
            if (dataRow.IsNull(columnName) || index < 0 || index > dataRow.ItemArray.Count())
            {
                return default(T);
            }
            else
            {
                return (T)dataRow[index];
            }
        }

请在下面检查它是否对您有用

private static DataSet SetDefaultForNull(DataSet dataSet)
{
    var retDataSet = new DataSet();
    for (int intTableCount = 0, loopTo = dataSet.Tables.Count - 1; intTableCount <= loopTo; intTableCount++)
    {
        DataTable dt = dataSet.Tables(intTableCount).Rows.Cast<DataRow>().Where(row => !row.ItemArray.All(field => object.ReferenceEquals(field, DBNull.Value) | field.Equals(""))).CopyToDataTable();


        retDataSet.Tables.Add(dt);
        foreach (DataRow row in retDataSet.Tables(intTableCount).Rows)
        {

            foreach (DataColumn col in retDataSet.Tables(intTableCount).Columns)
            {
                if (row(col) is DBNull)
                {
                    string dataType = col.DataType.ToString;
                    switch (col.DataType.ToString)
                    {
                        case "System.DateTime":
                            {
                                row(col) = new DateTime();
                                break;
                            }
                        case "System.String":
                            {
                                row(col) = string.Empty;
                                break;
                            }
                        case "System.Boolean":
                            {
                                row(col) = false;
                                break;
                            }
                        // row(col) = Nothing
                        case "System.Double":
                            {
                                break;
                            }
                        default:
                            {
                                row(col) = 0;
                                break;
                            }
                    }
                }
                // retDataSet.Tables(intTableCount).Columns.Add(col)
            }
            // retDataSet.Tables(intTableCount).Rows.Add(row.ItemArray)

        }
    }

    return retDataSet; // dataSet
}

如果您想检索字符串,无论在列中存储的是什么类型,都可以使用下面的方法

Utils.GetDbValue<object>(dr, "comments")?.ToString();

但是你的函数GetDbValue不支持空值和潜在的一些其他边缘情况,所以我建议使用内置的Field<T>()方法

public static T GetDbValue<T>(DataRow dataRow, string columnName)
{
    int index = dataRow.Table.Columns.IndexOf(columnName);
    if (index < 0 || index > dataRow.ItemArray.Count())
    {
        return default(T);
    }
    else
    {
        return dataRow.Field<T>(columnName);
    }
}

但是,只有当您希望在DataTable中不存在列的情况下返回默认值时才需要此代码。如果您不需要此检查,那么您可以简单地使用dr["comments"].ToString()作为字符串检索值,dr.Field<T>(columnName)用于其他情况。

最新更新