I'm still very new to C# so please bear with me. I have an Access database with a table that looks like this:
ID1 ID2 Name
----------------------
1111 1234567 Joe
2222 1234567 Patricia
3333 7654321 Laurie
None of the fields contain null values. I'm trying to store the length of the longest text representation of the values of each column in a DataTable
.
Based on rein's answer to this similar question, I included this handy generic function:
public static T ConvertFromDBVal<T>(object obj)
{
if (obj == null || Convert.IsDBNull(obj))
return default(T);
else
return (T)obj;
}
I get the data from the table as follows:
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;
}
The debugger gets mad at schemaRow.SetField(...)
and says:
Cannot cast DBNull.Value to type 'System.Int32'. Please use a nullable type.
So I tried using a nullable type. I replaced
schemaTable.Columns.Add("_maxCharLength", typeof(int?)); // was typeof(int)
Then the debugger says
DataSet does not support System.Nullable<>.
So I changed it back to int
. Even though I used the function to convert any null values, I checked the values and their types in the foreach
loop as follows:
Console.WriteLine("{0}, {1}, {2}, {3}",
tableName,
schemaRow.Field<string>("ColumnName"),
maxCharLength,
maxCharLength.GetType());
This works with no problem at all. I get the following in the console:
Table1, ID1, 4, System.Int32
Table1, ID2, 7, System.Int32
Table1, Name, 8, System.Int32
No null values, no exceptions, everything is as I expect it to be. Then why won't SetField
let me put those values in the DataTable
?
I think you need to change the line for SetField to
schemaRow.SetField("_maxCharLength", maxCharLength);
The DataRow.SetField extension requires for its first parameter the name of the column, or the ordinal position of the column inside the columns collection or a DataColumn instance.
The error message is caused by the fact that you try to read the value of the _maxCharLength
field using the DataRow.Field<T>
extension. But at that point of your code the _maxCharLength
field is still null because you have not yet set any value for it.
The compiler cannot warn you about this error because from a logical point of view you are calling a valid overload of the SetField extension. The one that requires an integer to express the ordinal position of the column to set value for.