Inserting DataTable into Oracle8i Database Table - c#

How do I insert a DataTable contents into Oracle8i Database Table?
1) This is how I did it. I want to know if this is would work:
I made this foreach loop to update the Oracle 8i Database table TABLE using the data from DataTable dt. TABLE and dt has the exact same columns:
Basically, what I did is to fetch the column names of the data table and use that in the insert query and doing the insert row by row:
below is the code:
DataTable dt;
int intColCtr1 = 1;
int intColCtr2 = 1;
strBTConn = strProvider + strUID + strPWD + strDataSource + strPersistSecurityInfo;
OLEDBconn.Open();
foreach (DataRow row in dt.Rows)
{
strSQL = "insert into TABLE ( ";
foreach (DataColumn column in dt.Columns)
{
if (intColCtr1<=dt.Columns.Count)
{
strSQL = " " + column.ColumnName.ToString() + ", ";
}
else
{
strSQL = " " + column.ColumnName.ToString() + " ";
intColCtr1++;
}
}
strSQL = " ) values ";
foreach (DataColumn column in dtUpdatedLACTM00.Columns)
{
if (intColCtr2<=dt.Columns.Count)
{
strSQL = " " + column.ToString() + ", ";
}
else
{
strSQL = " " + column.ToString() + " ";
intColCtr2++;
}
}
using (OleDbCommand OLEDBcmd = new OleDbCommand(strSQLCmd, OLEDBconn))
{
OLEDBcmd.ExecuteNonQuery();
}
}
[edit]: The above code failed because the data in the data table contained oracle and c# escape characters (single quotes and backslashes)
2) Also, if you have better ideas to update the database TABLE using data from DataTable dt, please tell me.

Related

Syntax error (missing operator) in query expression in C# script task in SSIS

I get this error:
System.Data.OleDb.OleDbException (0x80040E14): Syntax error (missing operator) in query expression ''O'Brien','O'Brien''.
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr)
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
at System.Data.OleDb.OleDbCommand.ExecuteNonQuery()
at ST_fc2b814c7d4843308992fd44a2168035.ScriptMain.Main()
This is the code I am using this query in C# script:
string queryString = "SELECT * FROM " + SchemaName + "." + TableName + " with(nolock) WHERE mfid IN " + "('"+ MFID + "')" +" AND activeflag = 'Y' AND ga_id NOT IN ('DPN') ORDER BY EmpID, ga_id";
C# script:
try
{
// Declare Variables
string MFID = Dts.Variables["User::MFID"].Value.ToString();
string ExcelPROD =MFID + Dts.Variables["User::ExcelPROD"].Value.ToString();
string FolderPath = Dts.Variables["User::FolderPath"].Value.ToString()+MFID+"\\";
OleDbConnection Excel_OLE_Con = new OleDbConnection();
OleDbCommand Excel_OLE_Cmd = new OleDbCommand();
//Construct ConnectionString for Excel
string connstring = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + FolderPath + ExcelPROD
+ ";" + "Extended Properties=\"Excel 12.0 Xml;HDR=YES;\"";
// Drop Excel file if exists
File.Delete(FolderPath + "\\" + ExcelPROD + ".xlsx");
// Use ADO.NET Connection from SSIS Package to get data from table
SqlConnection myADONETConnection = new SqlConnection();
myADONETConnection = (SqlConnection)(Dts.Connections["PROD"].AcquireConnection(Dts.Transaction) as SqlConnection);
string SchemaName = "dbo";
string TableName = "MASTER_DATA_EMPLOYEE";
// Load Data into DataTable from SQL ServerTable
// Assumes that connection is a valid SqlConnection object.
string queryString = "SELECT * FROM " + SchemaName + "." + TableName + " with(nolock) WHERE mfid IN ('" + MFID + "')" + " AND activeflag = 'Y' AND ga_id NOT IN ('DPN') ORDER BY EmpID,ga_id";
SqlDataAdapter adapter = new SqlDataAdapter(queryString, myADONETConnection);
DataSet ds = new DataSet();
adapter.Fill(ds);
//Get Header Columns
string TableColumns = "";
// Get the Column List from Data Table so can create Excel Sheet with Header
foreach (DataTable table in ds.Tables)
{
foreach (DataColumn column in table.Columns)
{
TableColumns += column + "],[";
}
}
// Replace most right comma from Columnlist
TableColumns = ("[" + TableColumns.Replace(",", " Text,").TrimEnd(','));
TableColumns = TableColumns.Remove(TableColumns.Length - 2);
//MessageBox.Show(TableColumns);
//Use OLE DB Connection and Create Excel Sheet
Excel_OLE_Con.ConnectionString = connstring;
Excel_OLE_Con.Open();
Excel_OLE_Cmd.Connection = Excel_OLE_Con;
Excel_OLE_Cmd.CommandText = "Create table [" + SchemaName + "_" + TableName + "] (" + TableColumns + ")";
Excel_OLE_Cmd.ExecuteNonQuery();
//Write Data to Excel Sheet from DataTable dynamically
foreach (DataTable table in ds.Tables)
{
String sqlCommandInsert = "";
String sqlCommandValue = "";
foreach (DataColumn dataColumn in table.Columns)
{
sqlCommandValue += dataColumn + "],[";
}
sqlCommandValue = "[" + sqlCommandValue.TrimEnd(',');
sqlCommandValue = sqlCommandValue.Remove(sqlCommandValue.Length - 2);
sqlCommandInsert = "INSERT into [" + SchemaName + "_" + TableName + "] (" + sqlCommandValue + ") VALUES(";
int columnCount = table.Columns.Count;
foreach (DataRow row in table.Rows)
{
string columnvalues = "";
for (int i = 0; i < columnCount; i++)
{
int index = table.Rows.IndexOf(row);
columnvalues += "'" + table.Rows[index].ItemArray[i] + "',";
}
columnvalues = columnvalues.TrimEnd(',');
var command = sqlCommandInsert + columnvalues + ")";
Excel_OLE_Cmd.CommandText = command;
Excel_OLE_Cmd.ExecuteNonQuery();
}
}
Excel_OLE_Con.Close();
Dts.TaskResult = (int)ScriptResults.Success;
}
The main issue is that the MFID variable using while building your query contains a quotation mark which is used for string literals in SQL Server.
System.Data.OleDb.OleDbException (0x80040E14): Syntax error (missing operator) in query expression ''O'Brien','O'Brien''.
You can solve this issue by parametrizing your SQL command. Lots of tutorials and step-by-step guides are found online. As an example:
Working With the SqlParameter Class in ADO.NET
Since you are using the MFID variable within the IN () clause, you can refer to the following answers to solve this issue:
How to pass sqlparameter to IN()?
Pass Array Parameter in SqlCommand

Attempting to migrate data from a spreadsheet to a Database using C# / ASP.NET

I have an Excel spreadsheet that I receive that I need to import into a table in our database. I have previously asked about pulling a single cell of data from a spreadsheet (Read a single cell from Excel to a string using C# and ASP.NET) and I am attempting to build off of this in order to move an entire spreadsheet into the database.
The format of the information is Column 1 = Name, Column 2 = Wage, Column 3 = Department
The existing code is as follows:
#region Initialize Connection
var Class_Connection = new SQL_Connection();
var sql = new SQL_Statements();
Class_Connection.cnn.Close();
#endregion
string properties = String.Format(#"Provider = Microsoft.ACE.OLEDB.12.0; Data Source = \\Hera\Public\LumberPrices\lbr_ems.xls; Extended Properties = 'Excel 8.0; HDR = NO;'");
string Price = "";
using (OleDbConnection conn = new OleDbConnection(properties))
{
string sqlpull = "SELECT * FROM [" + worksheet + "$" + Cell1 + ":" + Cell2 + "]";
conn.Open();
DataSet ds = new DataSet();
//string columns = String.Join(",", columnNames.ToArray());
using (OleDbDataAdapter da = new OleDbDataAdapter(sqlpull, properties))
{
string temp2 = "";
var dt = new DataTable();
da.Fill(dt);
for (int i = 0; i < dt.Columns.Count; i++)
{
temp2 = dt.Columns[i].ColumnName.ToString();
}
foreach (DataRow dr in dt.Rows)
{
Price = dr[temp2].ToString();
}
}
}
int Freight = GetFreight(LumbDesc);
int price1 = Convert.ToInt32(Price);
int addon = Convert.ToInt32(AddTo);
int Total = price1 + addon + Freight;
//TODO: insert into TLumberprice
string sqlStatement = "insert table([LumberCode], [Price], [PriceDate], [UserName], [Factor], [Op])" +
"values ('" + LumbDesc + "', '" + Total + "', '" + DateTime.Now + "', '" + LoginSession.userName.Remove(LoginSession.userName.Length - 1) + "', '" + Factor + "', '" + OP + "')";
#region Insert Lumber Prices
Class_Connection.cnn.Open();
SqlCommand InsertLumberPrices = new SqlCommand(sqlStatement, Class_Connection.cnn);
InsertLumberPrices.ExecuteNonQuery();
Class_Connection.cnn.Close();
#endregion
This works as intended. but I have questions.
Can I read the DataTable(dt) straight into the database, or do I have to use something like the following?
for (int i = 0; i < dt.Columns.Count; i++)
{
SName = dt.Columns[0].ColumnName.ToString();
SWage = dt.Columns[1].ColumnName.ToString();
SDept = dt.Columns[2].ColumnName.ToString();
}
foreach (DataRow dr in dt.Rows)
{
Name = dr[SName].tostring();
Wage = dr[SWage].tostring();
Dept = dr[SDept].tostring();
}
There is a way of importing the data from a data table into the SQL Table.
You need to use SqlBulkCopy
var sqlBulkCopy = new SqlBulkCopy(conn);
You can even map which data table column goes to which SQL Table column as well.
Here is an example.
using(var sqlBulkCopy = new SqlBulkCopy(conn))
{
sqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("Column 1", "Name"));
sqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("Column 2", "Wage"));
sqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("Column 3", "Department"));
sqlBulkCopy.DestinationTableName = "table" // table name in SQL
conn.Open();
sqlBulkCopy.WriteToServer(dt);
conn.Close();
}
Where conn is your SqlConnection.
If you don't want to use the data table, you could go directly to the BulkImport.
Just change the OleDbDataAdapter to OleDbCommand and put the value in an IDataReader variable, which then you can use in the code above instead of dt.
With the last part, I only did it in the past between 2 SQL servers that did not have a link to each other. I'm not sure 100% sure if it will work with OleDb.

Error: System.Data.OleDb.OleDbException (0x80040E14): Syntax error (missing operator) in query expression

I'm trying to export the results of a stored procedure to Excel and receiving the following error when running: System.Data.OleDb.OleDbException (0x80040E14): Syntax error (missing operator) in query expression. Below is the code I am using. The excel file gets created but there is no data populating the file.
string TableColumns = "";
// Get the Column List from Data Table so can create Excel Sheet with Header
foreach (DataTable table in ds.Tables)
{
foreach (DataColumn column in table.Columns)
{
TableColumns += column + "],[";
}
}
// Replace most right comma from Columnlist
TableColumns = ("[" + TableColumns.Replace(",", " Text,").TrimEnd(','));
TableColumns = TableColumns.Remove(TableColumns.Length - 2);
//Use OLE DB Connection and Create Excel Sheet
Excel_OLE_Con.ConnectionString = connstring;
Excel_OLE_Con.Open();
Excel_OLE_Cmd.Connection = Excel_OLE_Con;
Excel_OLE_Cmd.CommandText = "Create table " + SheetName + " (" + TableColumns + ")";
Excel_OLE_Cmd.ExecuteNonQuery();
//Write Data to Excel Sheet from DataTable dynamically
foreach (DataTable table in ds.Tables)
{
String sqlCommandInsert = "";
String sqlCommandValue = "";
foreach (DataColumn dataColumn in table.Columns)
{
sqlCommandValue += dataColumn + "],[";
}
sqlCommandValue = "[" + sqlCommandValue.TrimEnd(',');
sqlCommandValue = sqlCommandValue.Remove(sqlCommandValue.Length - 2);
sqlCommandInsert = "INSERT into " + SheetName + "(" + sqlCommandValue + ") VALUES(";
int columnCount = table.Columns.Count;
foreach (DataRow row in table.Rows)
{
string columnvalues = "";
for (int i = 0; i < columnCount; i++)
{
int index = table.Rows.IndexOf(row);
columnvalues += "'" + table.Rows[index].ItemArray[i] + "',";
}
columnvalues = columnvalues.TrimEnd(',');
var command = sqlCommandInsert + columnvalues + ")";
Excel_OLE_Cmd.CommandText = command;
Excel_OLE_Cmd.ExecuteNonQuery();
}
}
Excel_OLE_Con.Close();
Dts.TaskResult = (int)ScriptResults.Success;
So the issue is related to you have an unescaped single quote in your data. Two options for dealing with that are to escape the single quote (turn it into two single quotes):
string myData = "This string won't work";
string myDataEscaped = myData.Replace("'", "''");
or the other option (and more robust) is to use a parameterized query. I will use just the lower part of your code where you are doing this query build up and insertion and show you how that can be done (along with some cleanup and making use of StringBuilder). Note I did not compile and test this as I don't have any test data to use.
var tableColumns = string.Join(",", columns.Cast<DataColumn>().Select(x => "[" + x.ColumnName + "]"));
var insertBase = $"INSERT into {SheetName} ({tableColumns}) VALUES(";
int columnCount = table.Columns.Count;
foreach (DataRow row in table.Rows)
{
Excel_OLE_Cmd.Parameters.Clear(); // Since you are reusing the command you have to clear the parameters
var command = new StringBuilder(insertBase);
var index = table.Rows.IndexOf(row);
// I will assume you always have at least one column, otherwise these lines would fail
// Add the first row before the loop that way we don't have to delete the end comma
var param = $"#param_{index}_0";
command.Append(param);
Excel_OLE_Cmd.Parameters.AddWithValue(param, table.Rows[index].ItemArray[0]);
for (int i = 1; i < columnCount; ++i)
{
param = $"#param_{index}_{i}"
command.Append("," + param);
Excel_OLE_Cmd.Parameters.AddWithValue(param, table.Rows[index].ItemArray[i]);
}
command.Append(")");
Excel_OLE_Cmd.CommandText = command.ToString();
Excel_OLE_Cmd.ExecuteNonQuery();
}

Insert from datagridview to SQL with dynamic column names

Having imported data from an excel spreadsheet into datagridview, I would like to create a table (determined by the user in Windows forms) and insert it with the column names into the new table from the datagridview.
The user can use the "program" to insert other excel sheets into other databases as well.
How do I add column names dynamically that is not predefined and is defined by how many columns is in the excel spreadsheet?
My goal here was to create an import application to import excel spreadsheets into a SQL server database. The problem that I faced is to get the number columns that I needed to insert into the database and to dynamically name them according to the excel spreadsheet.
The application will be used on various spreadsheets and the column names must not be hardcoded. This is the code I used that managed the last phase of the application where all the data from the spreadsheet is inserted into to the database in SQL.
//Import Button
private void button5_Click(object sender, EventArgs e)
{
string createColumns = "";
string columns = "";
string rows = "";
var grid = (DataTable)dataGridView3.DataSource;
for (int i = 0; i < grid.Columns.Count; i++)
{
if (i == grid.Columns.Count - 1)
{
createColumns += "[" + grid.Columns[i].ToString() + "] varchar(200) NULL";
columns += "[" + grid.Columns[i].ToString() + "]";
}
else
{
columns += "[" + grid.Columns[i].ToString() + "],";
createColumns += "[" + grid.Columns[i].ToString() + "] varchar(200) NULL,";
}
}
string createTable = string.Format("Create table [{0}] ({1})", textBox1.Text, createColumns);
rows = string.Format("Insert Into[{0}]({1})", textBox1.Text, columns);
for (int i = 0; i < grid.Rows.Count; i++)
{
string row = "";
for (int c = 0; c < grid.Columns.Count; c++)
{
if (c == grid.Columns.Count - 1)
row += "'" + grid.Rows[i][c].ToString() + "'";
else
row += "'" + grid.Rows[i][c].ToString() + "', ";
}
if (i == grid.Rows.Count - 1)
rows += string.Format(" ({0});", row);
else
{
if (i == 0)
{
rows += " Values";
}
rows += string.Format(" ({0}),", row);
}
}
string s = "Integrated Security = SSPI;Persist Security Info = False;Data Source = " +
ServerName.Text + "; Initial Catalog = " +
Databases.Text;
SqlConnection conn = new SqlConnection(s);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = createTable;
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
SqlCommand cmd2 = new SqlCommand(rows, conn);
cmd2.CommandType = CommandType.Text;
conn.Open();
cmd2.ExecuteNonQuery();
conn.Close();
Application.Exit();
}

Paradox Inserting data Operation must use an updateable query

I am attempting to write to a Paradox database file using c# and oledb in Windows 8. I am able to drop the table, create the table and write the first line before I get the error "operation must use an updateable query".
I have gone through the following to try and work it out:
1) Running as administrator
2) Updating the permissions within the application to make sure I don't have readonly or archive properties on the file
3) Adding the running user permissions to read / write / modify directories where the db files sit
4) Changing the query multiple times in case I am doing something weird with the query
If I was unable to write or insert at all then the above steps would have made sense but the initial insert works and any additional inserts fail.
The code below shows the current way I am trying to perform the actions and I have left in the commented out sections so that you can see what else I have tried.
public void OverwriteData(string fileName, DataTable dataToWrite)
{
//split up the filename
string path = Path.GetDirectoryName(fileName);
string file = Path.GetFileName(fileName);
//create the string for creating the table
string strTempCreate = "";
//string strTempInsert = "";
foreach (DataColumn column in dataToWrite.Columns)
{
if (strTempCreate != "")
{
strTempCreate = strTempCreate + ", ";
}
strTempCreate = strTempCreate + "[" + column.ColumnName + "]" + " char(30)";
/*if (strTempInsert != "")
{
strTempInsert = strTempInsert + ", ";
}
strTempInsert = strTempInsert + column.ColumnName;*/
}
string createTableStr = "CREATE TABLE " + file + " (" + strTempCreate + ")";
string dropTableStr = "DROP TABLE " + file;
//build the sql insert command
//string insertSql = "insert into " + file + " values ";
/*foreach (DataRow row in dataToWrite.Rows)
{
insertSql = insertSql + row.Field<string>;
}*/
string connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + #";Extended Properties=Paradox 5.x;";
//DataTable results = new DataTable();
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbCommand dbCommand = new OleDbCommand();
dbCommand.Connection = conn;
dbCommand.CommandText = dropTableStr;
try
{
dbCommand.ExecuteNonQuery();
}
catch { }
dbCommand.CommandText = createTableStr;
dbCommand.ExecuteNonQuery();
//try to do the insert
StringBuilder sb = new StringBuilder();
//make sure that the database is not readonly
FileAttributes attributes = File.GetAttributes(fileName);
if ((attributes & FileAttributes.Archive) == FileAttributes.Archive)
{
attributes = attributes & ~FileAttributes.Archive;
File.SetAttributes(fileName, attributes);
}
//then we want to try and connect to this database to put data into it
string selectSQL = "Select * from " + file;
using (var adapter = new OleDbDataAdapter(selectSQL, conn))
{
using (var builder = new OleDbCommandBuilder(adapter))
{
var destinationTable = new DataTable();
adapter.Fill(destinationTable);
destinationTable.Merge(dataToWrite,true,MissingSchemaAction.Ignore);
destinationTable.AcceptChanges();
foreach (DataRow row in destinationTable.Rows)
{
row.SetAdded();
}
builder.QuotePrefix = "[";
builder.QuoteSuffix = "]";
builder.GetInsertCommand();
adapter.Update(destinationTable);
}
}
/*foreach (DataRow row in dataToWrite.Rows)
{
sb.Clear();
sb.Append("insert into " + file + " values ('");
IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
sb.Append(string.Join("','", fields));
sb.Append("')");
dbCommand.CommandText = sb.ToString();
dbCommand.ExecuteNonQuery();
}*/
/*sb.Clear();
sb.Append("insert into " + file);
foreach (DataRow row in dataToWrite.Rows)
{
sb.Append(" values ('");
IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
sb.Append(string.Join("','", fields));
sb.Append("'),");
}
sb.Remove(sb.Length - 1, 1);
sb.Append(";");
dbCommand.CommandText = sb.ToString();
dbCommand.ExecuteNonQuery();
*/
}
}
This article solved my problem: https://msdn.microsoft.com/en-us/library/ms715421(v=vs.85).aspx
According to Microsoft: A table is not updatable by the Paradox driver under two conditions:
When a unique index is not defined on the table. This is not true for
an empty table, which can be updated with a single row even if a
unique index is not defined on the table. If a single row is inserted
in an empty table that does not have a unique index, an application
cannot create a unique index or insert additional data after the
single row has been inserted.
If the Borland Database Engine is not implemented.

Categories

Resources