Reputation: 181
I am writing a very simple method to convert a csv to a datatable so it can be inserted into a SQL database. It works exactly how it should, unless I try to replace empty strings with DBNull.Value, then it throws an ArrayTypeMismatchException. The stream coming in is a simple comma-separated file with the data.
The problem code:
public static DataTable StreamToTable(Stream stream, bool headersAvailable, bool convertBlankToDBNull)
{
DataTable data = new DataTable();
StreamReader reader = new StreamReader(stream);
if (!reader.EndOfStream)
{
if (headersAvailable)
{
try
{
//get headers from first line
string[] headers = reader.ReadLine().Split(',');
//construct headers
for (int i = 0; i < headers.Length; i++)
{
data.Columns.Add(headers[i]);
}
}
catch (IOException ioEx)
{
return null;
}
}
while (!reader.EndOfStream)
{
object[] row = reader.ReadLine().Split(',');
if (convertBlankToDBNull)
{
for (int i = 0; i < row.Length; i++)
{
if (row[i].ToString().Equals(""))
{
row[i] = DBNull.Value; //this is where I get the exception
}
}
}
data.Rows.Add(row);
}
return data;
}
else return null;
}
I can't figure out what I am doing wrong... I should be able to assign anything to the array because it's an object array, so how can there be a type mismatch?
Upvotes: 2
Views: 1175
Reputation: 887807
You've discovered the horrors of unsafe array covariance.
row
is a string[]
that has been unsafely cast to object[]
. Even though that cast succeeds, the array is still a string[]
(since that's what Split()
returns), and cannot be used as an object[]
.
In particular, it still can't hold things that aren't string
s.
Instead, you can create a new object[]
and populate it with those string
s:
object[] row = Array.ConvertAll(
reader.ReadLine().Split(','),
s => (object)s
);
Upvotes: 3