我有一个装载了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)
用于其他情况。