tags:

views:

185

answers:

2

Hi,

I have a System.Data.DataTable which is populated by reading a CSV file which sets the datatype of each column to string.

I want to append the contents of the DataTable to an existing database table - currently this is done using SqlBulkCopy with the DataTable as the source.

However, the column data types of the DataTable need to be changed to match the schema of the target database table, handling null values.

I am not very familiar with ADO.NET so have been searching for a clean way of doing this?

Thanks.

A: 

Be sure to set the datatypes of the datatable you're filling up.

E.g.:

    DataTable table = new DataTable("countries");
    table.Columns.Add("country_code", typeof (string));
    table.Columns.Add("country_name", typeof (string));
    //...
    //Fill table

Or you could change the column types if they are compatible:

table.Columns["country_code"].DataType = typeof(string);
Carra
Yep, this is what I am currently doing but actually populating the second DataTable with the types correctly set is proving difficult. Is there a simple way to do this?
TonE
+2  A: 

You cannot change the DataType of a DataColumn after populating it with data. It's not a read-only property, but you will receive an exception at runtime if you attempt to change it after it already has data.

From the documentation:

An exception is generated when changing this property after the column has begun storing data.

So you will have to either ensure the correct column types in the beginning (if possible), or create a new DataTable specifically for the import and copy data from the original DataTable.

You could also write a custom IDataReader class that reads from your DataTable and performs just-in-time conversion and pass that to the SqlBulkCopy - it would be a lot more efficient, but it's obviously not a quick fix.

Aaronaught
Thanks - I realise I can't change it once populated. What I am looking for is a way of creating a second DataTable with the correct data types and then importing and converting the data from the first DataTable. It is not possible for the first DataTable to use data types other than String unfortunately.
TonE
@TonE: The only way I can think of to do that would be to implement `IDataReader` and use the `DataTable.Load` method - but if you're going to do that, you might as well just use the reader itself for `SqlBulkCopy` instead of creating a second `DataTable`.
Aaronaught
That's an interesting suggestion. Would it be possible to derive from DataTableReader, and if so do you know which methods I would need to override to provide the type changing functionality? Just trying to gauge if it is plausible given the time constraints.
TonE
@TonE: `DataTableReader` is sealed, so no, you'd have to write one from scratch. Even if you could subclass it, you'd have to override almost every method anyway, so it'd be easier to just make your own. Your `IDataReader` implementation would have to define its own list of columns/fields (possibly just a `List<Type>`) and use the `Convert` class on the original string data. I'm not sure, but I think you'd also have to provide a valid implementation of `GetSchemaTable` in order to make it work with `SqlBulkCopy`... that's the hard part.
Aaronaught
Thanks for your help. I haven't time to implement this at the moment so have modified the CSV reading code to take a typed DataTable and replace error values with null using a FillErrorEventHandler. Could have done this in the first instance really! The custom IDataReader is a good idea though, will try it out in future.
TonE