Search code examples
linqdatatableinsertoledb

Reading/Writing DataTables to and from an OleDb Database LINQ


My current project is to take information from an OleDbDatabase and .CSV files and place it all into a larger OleDbDatabase.

I have currently read in all the information I need from both .CSV files, and the OleDbDatabase into DataTables.... Where it is getting hairy is writing all of the information back to another OleDbDatabase.

Right now my current method is to do something like this:

    OleDbTransaction myTransaction = null;

    try
    {
        OleDbConnection conn = new OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;" +
                                                   "Data Source=" + Database);
        conn.Open();
        OleDbCommand command = conn.CreateCommand();
        string strSQL;

        command.Transaction = myTransaction;

        strSQL = "Insert into TABLE " +
                 "(FirstName, LastName) values ('" +
                 FirstName + "', '" + LastName + "')";

        command.CommandType = CommandType.Text;
        command.CommandText = strSQL;

        command.ExecuteNonQuery();

        conn.close();

    catch (Exception)
        {
            // IF invalid data is entered, rolls back the database
            myTransaction.Rollback();
        }

Of course, this is very basic and I'm using an SQL command to commit my transactions to a connection. My problem is I could do this, but I have about 200 fields that need inserted over several tables. I'm willing to do the leg work if that's the only way to go. But I feel like there is an easier method. Is there anything in LINQ that could help me out with this?


Solution

  • If the column names in the DataTable match exactly to the column names in the destination table, then you might be able to use a OleDbCommandBuilder (Warning: I haven't tested this yet). One area you may run into problems is if the data types of the source data table do not match those of the destination table (e.g if the source column data types are all strings).

    EDIT I revised my original code in a number of ways. First, I switched to using the Merge method on a DataTable. This allowed me to skip using the LoadDataRow in a loop.

    using ( var conn = new OleDbConnection( destinationConnString ) )
    {
        //query off the destination table. Could also use Select Col1, Col2..
        //if you were not going to insert into all columns.
        const string selectSql = "Select * From [DestinationTable]";
    
        using ( var adapter = new OleDbDataAdapter( selectSql, conn ) )
        {
            using ( var builder = new OleDbCommandBuilder( adapter ) )
            {
                conn.Open();
    
                var destinationTable = new DataTable();
                adapter.Fill( destinationTable );
    
                //if the column names do not match exactly, then they 
                //will be skipped
                destinationTable.Merge( sourceDataTable, true, MissingSchemaAction.Ignore );
    
                //ensure that all rows are marked as Added.
                destinationTable.AcceptChanges();
                foreach ( DataRow row in destinationTable.Rows )
                    row.SetAdded();
    
                builder.QuotePrefix = "[";
                builder.QuoteSuffix= "]";
    
                //forces the builder to rebuild its insert command
                builder.GetInsertCommand();
                adapter.Update( destinationTable );
            }
        }
    }
    

    ADDITION An alternate solution would be to use a framework like FileHelpers to read the CSV file and post it into your database. It does have an OleDbStorage DataLink for posting into OleDb sources. See the SqlServerStorage InsertRecord example to see how (in the end substitute OleDbStorage for SqlServerStorage).