2

我对 C# 还是很陌生,所以请多多包涵。我有一个带有如下表的 Access 数据库:

ID1  ID2     Name
----------------------
1111 1234567 Joe
2222 1234567 Patricia
3333 7654321 Laurie

所有字段都不包含空值。我正在尝试将每列值的最长文本表示的长度存储在DataTable.

根据 rein 对这个类似问题的回答,我包含了这个方便的通用函数:

public static T ConvertFromDBVal<T>(object obj)
{
    if (obj == null || Convert.IsDBNull(obj))
        return default(T);
    else
        return (T)obj;
}

我从表中获取数据如下:

public DataTable GetMetadata(string tableName)
{
    ...

    // My OLEDB connection _oleConnection is already open

    OleDbCommand selectTable = new OleDbCommand("SELECT * FROM [" +
        tableName + "]", _oleConnection);

    OleDbDataReader oleReader = selectTable.ExecuteReader();

    DataTable schemaTable = oleReader.GetSchemaTable().Copy();
    schemaTable.Columns.Add("_maxCharLength", typeof(int));

    foreach (DataRow schemaRow in schemaTable.Rows)
    {
        OleDbCommand getMax = new OleDbCommand();
        getMax.Connection = _oleConnection;

        // Convert non-text fields to strings before getting lengths

        if (schemaRow.Field<Type>("DataType") == typeof(string))
        {
            getMax.CommandText = "SELECT MAX(LEN(" +
                schemaRow.Field<string>("ColumnName") + ")) FROM " +
                tableName;
        }
        else
        {
            getMax.CommandText = "SELECT MAX(LEN(STR(" +
                schemaRow.Field<string>("ColumnName") + "))) FROM " +
                tableName;
        }

        int maxCharLength = ConvertFromDBVal<int>(getMax.ExecuteScalar());

        schemaRow.SetField(schemaRow.Field<int>("_maxCharLength"),
            maxCharLength);

        getMax.Dispose();
        getMax = null;
    }

    ...

    return schemaTable;
}

调试器生气schemaRow.SetField(...)并说:

Cannot cast DBNull.Value to type 'System.Int32'. Please use a nullable type.

所以我尝试使用可为空的类型。我换了

schemaTable.Columns.Add("_maxCharLength", typeof(int?));   // was typeof(int)

然后调试器说

DataSet does not support System.Nullable<>.

所以我把它改回int. 尽管我使用该函数来转换任何空值,但我还是在foreach循环中检查了这些值及其类型,如下所示:

Console.WriteLine("{0}, {1}, {2}, {3}",
    tableName,
    schemaRow.Field<string>("ColumnName"),
    maxCharLength,
    maxCharLength.GetType());

这完全没有问题。我在控制台中得到以下信息:

Table1, ID1, 4, System.Int32
Table1, ID2, 7, System.Int32
Table1, Name, 8, System.Int32

没有空值,没有例外,一切都如我所料。那为什么SetField不让我把这些值放在DataTable?

4

1 回答 1

2

我认为您需要将 SetField 的行更改为

 schemaRow.SetField("_maxCharLength", maxCharLength);

DataRow.SetField扩展的第一个参数需要列的名称,或者列在列集合或 DataColumn 实例中的序号位置。

错误消息是由于您尝试使用扩展名读取 _maxCharLength字段的值而引起的。DataRow.Field<T>但是在您的代码中,该_maxCharLength字段仍然为空,因为您尚未为其设置任何值。

编译器无法警告您此错误,因为从逻辑角度来看,您正在调用 SetField 扩展的有效重载。需要一个整数来表示要为其设置值的列的序号位置。

于 2014-04-03T21:15:19.010 回答