Saving to DataBase using OleDB - c#

Im having a lot of trouble understanding OLEDB, im particularly struggling to get information to save to the database this is my current code to attempt to save:
Note: i can load the information absolutely fine, and when i run this function my information appears in my listBox however upon closing the application it hasnt saved.
If you could help explain the problem that would be great
void Insert_New_Log(int startfloor, int endfloor, string currentAction)
{
OleDbConnection conn = new OleDbConnection(dbconnection);
OleDbCommand comm = new OleDbCommand(dbcommand, conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(comm);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
// adapter.UpdateCommand = builder.GetUpdateCommand();
conn.Open();
adapter.Fill(ds, "ElevatorTable");
conn.Close();
DataRow newRow = ds.Tables[0].NewRow();
newRow["ID"] = 0;
newRow["Date1"] = dateAndTime;
newRow["StartingFloor"] = startfloor;
newRow["EndFloor"] = endfloor;
newRow["Action"] = currentAction;
ds.Tables[0].Rows.Add(newRow);
DataSet dataSetChanges = ds.GetChanges();
try
{
adapter.Update(dataSetChanges, "ElevatorTable");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
ds.AcceptChanges();
//update Visible list
dbListBox.Items.Clear();
foreach (DataRow row in ds.Tables[0].Rows)
{
dbListBox.Items.Add(row["ID"] + "\t" + row["Date1"] + "\t" + row["StartingFloor"] + "\t" + row["EndFloor"] + "\t" + " (" + row["Action"] + ")");
}
}
ive since put a write line in and found this exception.
Exception thrown: 'System.Data.OleDb.OleDbException' in System.Data.dll
System.Data.OleDb.OleDbException (0x80040E14): Syntax error in INSERT INTO statement.
at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
at System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
at System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping)
at System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable dataTable, DataTableMapping tableMapping)
at System.Data.Common.DbDataAdapter.Update(DataSet dataSet, String srcTable)
at System.Data.Common.DbDataAdapter.Update(DataSet dataSet)
at Elevator.Form1.Insert_New_Log(Int32 startfloor, Int32 endfloor, String currentAction) in C:\Users\Brads\Desktop\Elevator\Elevator\Form1.cs:line 197

you have closed the connection after filling the adapter. You need to either leave the connection open or re-open it.
adapter.Fill(ds, "ElevatorTable");
conn.Close();
Follow this by
conn.Open();

Does the user you have setup in the adapter have write permissions in the SQL database? Also you closed your connection before the update statement that will need to be open in order to write back.
void Insert_New_Log(int startfloor, int endfloor, string currentAction)
{
OleDbConnection conn = new OleDbConnection(dbconnection);
OleDbCommand comm = new OleDbCommand(dbcommand, conn);
OleDbDataAdapter adapter = new OleDbDataAdapter(comm);
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapter);
// adapter.UpdateCommand = builder.GetUpdateCommand();
conn.Open();
adapter.Fill(ds, "ElevatorTable");
DataRow newRow = ds.Tables[0].NewRow();
newRow["ID"] = 0;
newRow["Date1"] = dateAndTime;
newRow["StartingFloor"] = startfloor;
newRow["EndFloor"] = endfloor;
newRow["Action"] = currentAction;
ds.Tables[0].Rows.Add(newRow);
DataSet dataSetChanges = ds.GetChanges();
ds.AcceptChanges();
try
{
adapter.Update(dataSetChanges, "ElevatorTable");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally { conn.Close(); }
//update Visible list
dbListBox.Items.Clear();
foreach (DataRow row in ds.Tables[0].Rows)
{
dbListBox.Items.Add(row["ID"] + "\t" + row["Date1"] + "\t" + row["StartingFloor"] + "\t" + row["EndFloor"] + "\t" + " (" + row["Action"] + ")");
}
}

Related

Updating cells using dataset read from xls file and save to CSV file

can somebody tell me why this update procedure doesn't work? I want to read data to dataset from XLS and it works just fine but UPDATE doesn't work at all. No errors, no changes, like it doesn't exist. The file creates but values are just a copy from original xls.
Xls sheet format is pretty simple, one column: id 1 2 3
string string_conn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=path\name.xls;Extended Properties='Excel 8.0;HDR=Yes;'";
OleDbConnection conn = new OleDbConnection(string_conn);
conn.Open();
DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
comboBox1.DataSource = excelSheets;
string xlsSheet = comboBox1.SelectedItem.ToString();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + xlsSheet + "]", conn);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
adapter.UpdateCommand = new OleDbCommand ("UPDATE " + xlsSheet + " SET id = " + tbox1.Text + " WHERE id = " + tbox2.Text + "", conn);
adapter.UpdateCommand.Parameters.Add("#id", OleDbType.Char, 255).SourceColumn = "id";
adapter.UpdateCommand.Parameters.Add("#Oldid", OleDbType.Char, 255, "id").SourceVersion = DataRowVersion.Original;
adapter.Update(dataset);
dataset.AcceptChanges();
DataTable dtable = new DataTable();
dtable = dataset.Tables[0];
StringBuilder str = new StringBuilder();
foreach (DataRow dr in dtable.Rows)
{
foreach (var field in dr.ItemArray)
{
str.Append(field.ToString());
str.Append(", ");
}
str.Replace(",", str.AppendLine().ToString(), str.Length - 1, 1);
}
MessageBox.Show(str.ToString()); //for test's sake
string pathFile = #"path\filename.csv";
if (!File.Exists(pathFile))
{
File.Create(pathFile).Close();
}
File.AppendAllText(pathFile, str.ToString());
Something is wrong with parameters probably but I tried this way and also no go (I added 2nd column so id stays the same just to find proper row), I get UPDATE command syntax error on execute:
string string_conn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=path\arkusz.xls;Extended Properties='Excel 8.0;HDR=Yes;'";
OleDbConnection conn= new OleDbConnection(string_conn);
conn.Open();
DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
comboBox1.DataSource = excelSheets;
string xlsSheet = comboBox1.SelectedItem.ToString();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + xlsSheet + "]", conn);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
adapter.UpdateCommand = new OleDbCommand("UPDATE " + xlsSheet + " SET nazwa = #nazwa WHERE id = #id", conn);
adapter.UpdateCommand.Parameters.AddWithValue("#id", tbox1.Text).OleDbType = OleDbType.Integer;
adapter.UpdateCommand.Parameters.AddWithValue("#nazwa", tbox2.Text).OleDbType = OleDbType.VarChar;
adapter.UpdateCommand.ExecuteNonQuery();
adapter.Update(dataset);
dataset.AcceptChanges();
DataTable dtable = new DataTable();
dtable = dataset.Tables[0];
StringBuilder str = new StringBuilder();
foreach (DataRow dr in dtable.Rows)
{
foreach (var field in dr.ItemArray)
{
str.Append(field.ToString());
str.Append(", ");
}
str.Replace(",", str.AppendLine().ToString(), str.Length - 1, 1);
}
MessageBox.Show(str.ToString());
string sciezkaPlik = #"path\filename.csv";
if (!File.Exists(sciezkaPlik))
{
File.Create(sciezkaPlik).Close();
}
File.AppendAllText(sciezkaPlik, str.ToString());
I solved the issue. For future reference it works well like this:
string string_conn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=path\arkusz.xls;Extended Properties='Excel 8.0;HDR=Yes;'";
OleDbConnection conn = new OleDbConnection(string_conn);
conn.Open();
DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
string[] excelSheets = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheets[i] = row["TABLE_NAME"].ToString();
i++;
}
comboBox1.DataSource = excelSheets;
string xlsSheet = comboBox1.SelectedItem.ToString();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [" + xlsSheet + "]", conn);
DataSet dataset = new DataSet();
adapter.Fill(dataset);
OleDbCommand odbc = new OleDbCommand("UPDATE ["+xlsSheet+"] SET nazwa = " + txtNewValue.Text + " WHERE id = " + txtID.Text + "", conn);
adapter.UpdateCommand = odbc;
odbc.Parameters.AddWithValue("nazwa", txtNewValue.Text).OleDbType = OleDbType.VarChar;
odbc.Parameters.AddWithValue("id", txtID.Text).OleDbType = OleDbType.Integer;
odbc.ExecuteNonQuery();
dataset.Clear();
adapter.Fill(dataset);
DataTable dtable = new DataTable();
dtable = dataset.Tables[0];
StringBuilder str = new StringBuilder();
foreach (DataRow dr in dtable.Rows)
{
foreach (var field in dr.ItemArray) /
{
str.Append(field.ToString());
str.Append(", ");
}
str = str.Replace(',', '\n');
}
string filePath= #"path\filename.csv";
if (!File.Exists(filePath))
{
File.Create(filePath).Close();
}
File.WriteAllText(filePath, str.ToString());
EDIT - I think it may be that this line needs to have the parameters put in as a question mark instead of having the actual values passed in, so more like this:
adapter.UpdateCommand = new OleDbCommand ("UPDATE " + xlsSheet + " SET id = ? WHERE id = ?", conn);
Then your next couple of lines are correct, they are clever enough to replace the question marks from the UpdateCommand with the actual values at run time:
adapter.UpdateCommand.Parameters.Add("#id", OleDbType.Char, 255).SourceColumn = "id";
adapter.UpdateCommand.Parameters.Add("#Oldid", OleDbType.Char, 255, "id").SourceVersion = DataRowVersion.Original;
Hare is a very simple method to do an insert into an Excel sheet.
using System;
using System.Drawing;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
System.Data.OleDb.OleDbConnection MyConnection ;
System.Data.OleDb.OleDbCommand myCommand = new System.Data.OleDb.OleDbCommand();
string sql = null;
MyConnection = new System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='c:\\csharp.net-informations.xls';Extended Properties=Excel 8.0;");
MyConnection.Open();
myCommand.Connection = MyConnection;
sql = "Insert into [Sheet1$] (id,name) values('5','e')";
myCommand.CommandText = sql;
myCommand.ExecuteNonQuery();
MyConnection.Close();
}
catch (Exception ex)
{
MessageBox.Show (ex.ToString());
}
}
}
}

distinguish the columns of a stacked column chart

I want to draw a stacked chart from mysql database.
I want to have 4 columns named "port1", "port2", "port3" and "port4".
My problem is when I import the data from my DB, I check the type a column in the table then I draw the chart . My DB contains 4 types of port consequently I would have 4 columns named port1, port2, port3 and port4, but my code generate all the data but on the same column which is port1.
How can I add an identical number of datapoints?
try
{
con.Open();
string query1 = "SELECT type,name,value FROM " + server + " WHERE type LIKE '%port1'" ;
string query4 = "SELECT type,name,value FROM " + server + " WHERE type LIKE '%port4'";
SqlCommand cmmd = new SqlCommand(query1, con);
SqlCommand cmmd4 = new SqlCommand(query4, con);
SqlDataReader dataReader = cmmd.ExecuteReader();
while (dataReader.Read())
{
chart1.Series.Add(dataReader["name"].ToString());
chart1.Series[dataReader["name"].ToString()].ChartType = SeriesChartType.StackedColumn;
chart1.Series[dataReader["name"].ToString()]["StackedGroupName"] = "Group1";
chart1.Series[dataReader["name"].ToString()].Points.AddXY((dataReader["type"].ToString()), dataReader["value"].ToString());
}
con.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
try
{
con.Open();
string query1 = "SELECT type,name,value FROM " + server + " WHERE type LIKE '%port1'" ;
SqlCommand cmmd = new SqlCommand(query1, con);
SqlDataReader dataReader = cmmd.ExecuteReader();
while (dataReader.Read())
{
chart1.Series.Add(dataReader["name"].ToString());
chart1.Series[dataReader["name"].ToString()].ChartType = SeriesChartType.StackedColumn;
chart1.Series[dataReader["name"].ToString()]["StackedGroupName"] = "Group1";
chart1.Series[dataReader["name"].ToString()].Points.AddXY((dataReader["type"].ToString()), dataReader["value"].ToString());
}
con.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error " + ex);
}
try
{
con.Open();
string query2 = "SELECT type,name,value FROM " + server + " WHERE type LIKE '%port2'";
SqlCommand cmmd2 = new SqlCommand(query2, con);
SqlDataReader dataReader2 = cmmd2.ExecuteReader();
while (dataReader2.Read())
{
chart1.Series.Add(dataReader2["name"].ToString());
chart1.Series[dataReader2["name"].ToString()].ChartType = SeriesChartType.StackedColumn;
chart1.Series[dataReader2["name"].ToString()]["StackedGroupName"] = "Group2";
// MessageBox.Show(dataReader2["type"].ToString());
chart1.DataBind();
chart1.Series[dataReader2["name"].ToString()].Points.AddXY("Port_2", dataReader2["value"].ToString());
chart1.Series[dataReader2["name"].ToString()]["PointWidth"] = "1";
}
con.Close();
}
catch(Exception ex)
{
MessageBox.Show("Error "+ ex);
}

ADO.Net INSERT not inserting data

I've got a c#.Net 4.5 console application and I'm trying to insert data from a DataTable to a SQL Server 2008R2 database table. I get no errors, but no data gets inserted. Here's my code:
Int32 newID = 0;
DataTable dtMaxUserID = GeneralClassLibrary.GeneralDataAccessLayer.ExecuteSelect("SELECT MAX(UserID)+1 AS NewID FROM TIUser", false, "TrackitCN");
newID = Convert.ToInt32(dtMaxUserID.Rows[0]["NewID"].ToString());
//Get new users from AllUserData
DataColumn dcRowID = new DataColumn("RowID", typeof(Int32));
//dcRowID.AllowDBNull = false;
dcRowID.AutoIncrement = true;
dcRowID.AutoIncrementSeed = 1;
dcRowID.AutoIncrementStep = 1;
//dcRowID.Unique = true;
//dcRowID.ColumnName = "RowID";
DataTable dtNewUsers = new DataTable();
dtNewUsers.Columns.Add(dcRowID);
dtNewUsers.Columns.Add("MaxID");
dtNewUsers.Columns.Add("UserID");
dtNewUsers.Columns.Add("FullName");
dtNewUsers.Columns.Add("Title");
dtNewUsers.Columns.Add("Phone");
dtNewUsers.Columns.Add("EMailAddr");
dtNewUsers.Columns.Add("Fax");
dtNewUsers.Columns.Add("Dept");
dtNewUsers.Columns.Add("Dept_Num");
dtNewUsers.Columns.Add("Location");
dtNewUsers.Columns.Add("UserDef_1");
dtNewUsers.Columns.Add("UserDef_2");
dtNewUsers.Columns.Add("Login");
dtNewUsers.Columns.Add("Password");
dtNewUsers.Columns.Add("PasswordFlags");
dtNewUsers.Columns.Add("LanguageID");
dtNewUsers.Columns.Add("NTAuthentication");
dtNewUsers.Columns.Add("NTAccount");
dtNewUsers.Columns.Add("SID");
dtNewUsers.Columns.Add("SelfServiceAccess");
dtNewUsers.Columns.Add("ImagePath");
dtNewUsers.Columns.Add("CompFlag");
dtNewUsers.Columns.Add("Employee_ID");
dtNewUsers.Columns.Add("SessionID");
string strQuery = "SELECT " + newID + " AS MaxID, LName" + ", " + "FName AS FullName, Title, Phone, EMail AS EmailAddr, Fax, Department AS Dept, Office AS Location, [Login] AS Employee_ID FROM [User] WHERE StartDate >= CAST(DATEPART(year,getdate()) AS varchar) + '-' + CAST(DATEPART(month,getdate()) AS varchar) + '-' + CAST(DATEPART(day,getdate())-1 AS varchar)";
DataTable dtTemp = GeneralClassLibrary.GeneralDataAccessLayer.ExecuteSelect(strQuery, false, "AllUserDataCN");
foreach (DataRow row in dtTemp.Rows)
dtNewUsers.ImportRow(row);
SqlTransaction tran = null;
try
{
connection.Open();
tran = connection.BeginTransaction();
//Insert new users into TIUser
SqlDataAdapter TIUser_adapter = new SqlDataAdapter();
string queryString = "SELECT * FROM TIUser WHERE 1 = 0";
TIUser_adapter.SelectCommand = new SqlCommand(queryString, connection, tran);
TIUser_adapter.Fill(dtNewUsers);
dtNewUsers.AcceptChanges();
TIUser_adapter.Update(dtNewUsers);
tran.Commit();
}
catch (System.Exception ex)
{
tran.Rollback();
throw ex;
}
finally
{
connection.Close();
}
GeneralClassLibrary is a class library we use here for a number of things; here it just executes a SELECT statement on a database. TIUser is the database table. The DataTable, dtNewUsers contains one row. I've verified that by debugging the code and inspecting the DataTable after the ImportRow is done.
After following the reply from user3787557 (THANK YOU!), I'm closer, but I'm getting a concurrency violation. I'm working on a development database, and all I'm doing is inserting a record, so I have no idea why there'd be a concurrency violation. One possibility: I alter the structure of the DataTable dtNewUsers by adding two columns. However, before I do the update, I remove those columns. The InsertCommand is fine; I've checked it in SSMS and it parses. Here's my new code:
using (SqlConnection connection = new SqlConnection(GeneralClassLibrary.GeneralConfigurationManager.ConnectionStrings["TrackitCN"].ConnectionString))
{
SqlTransaction tran = null;
connection.Open();
tran = connection.BeginTransaction();
try
{
//Create empty TIUser Data Adapter
SqlDataAdapter TIUser_adapter = new SqlDataAdapter();
SqlCommandBuilder TIUser_builder = new SqlCommandBuilder(TIUser_adapter);
string queryString = "SELECT * FROM TIUser WHERE 1 = 0";
TIUser_adapter.SelectCommand = new SqlCommand(queryString, connection, tran);
TIUser_adapter.InsertCommand = TIUser_builder.GetInsertCommand();
TIUser_adapter.UpdateCommand = TIUser_builder.GetUpdateCommand();
//Get new users from AllUserData
DataTable dtNewUsers = new DataTable();
TIUser_adapter.Fill(dtNewUsers);
DataColumn dcRowID = new DataColumn("RowID", typeof(Int32));
dcRowID.AutoIncrement = true;
dcRowID.AutoIncrementSeed = 1;
dcRowID.AutoIncrementStep = 1;
dtNewUsers.Columns.Add(dcRowID);
dtNewUsers.Columns.Add("MaxID"); string strQuery = "SELECT " + newID + " AS MaxID, LName + ', ' + FName AS FullName, Title, Phone, EMail AS EmailAddr, Fax, Department AS Dept, Office AS Location, [Login] AS Employee_ID FROM [User] WHERE StartDate >= CAST(DATEPART(year,getdate()) AS varchar) + '-' + CAST(DATEPART(month,getdate()) AS varchar) + '-' + CAST(DATEPART(day,getdate())-1 AS varchar)";
DataTable dtTemp = GeneralClassLibrary.GeneralDataAccessLayer.ExecuteSelect(strQuery, false, "AllUserDataCN");
foreach (DataRow row in dtTemp.Rows)
dtNewUsers.ImportRow(row);
//Make sure new users aren't already in Trackit
foreach (DataRow row in dtNewUsers.Rows)
{
row["UserID"] = (Convert.ToInt32(row["RowID"]) + Convert.ToInt32(row["MaxID"])).ToString();
DataTable dtOverlap = GeneralClassLibrary.GeneralDataAccessLayer.ExecuteSelect("SELECT * FROM TIUser WHERE Employee_ID = '" + row["Employee_ID"].ToString() + "'", false, "TrackitCN");
if (dtOverlap.Rows.Count > 0)
dtNewUsers.Rows.Remove(row);
}
//Remove MaxID and RowID Columns
dtNewUsers.Columns.Remove("MaxID");
dtNewUsers.Columns.Remove("RowID")
TIUser_adapter.Update(dtNewUsers);
tran.Commit();
}
catch (System.Exception ex)
{
GeneralClassLibrary.GeneralEmail.ExceptionNotification(System.Reflection.Assembly.GetExecutingAssembly().ToString(), ex.Message, ex.StackTrace);
tran.Rollback();
throw ex;
}
finally
{
connection.Close();
}
}
The Stack Trace I get is:
at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
at System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
at System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping)
at System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable dataTable, DataTableMapping tableMapping)
at System.Data.Common.DbDataAdapter.Update(DataTable dataTable)
at UpdateTrackitUsers.Program.Main(String[] args) in c:\Users\06717\Documents\Visual Studio 2012\Projects\UpdateTrackitUsersConsole\UpdateTrackitUsersConsole\Program.cs:line 91
Line 87 is the line:
TIUser_adapter.Update(dtNewUsers);
This is the code that worked for me. Basically what you're missing on your code is to use SqlCommandBuilder to create InsertCommand and UpdateCommand. Also GET RID of AcceptChanges(). That is going to cause the new row to NOT be sent to the database. One last thing: make sure you mark the MDF database file (if you're using one) properties with "Do Not Copy" otherwise the database gets overridden every time you compile and you can't see your changes.
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
adapter.SelectCommand = new SqlCommand(queryString, connection);
adapter.InsertCommand = builder.GetInsertCommand();
adapter.UpdateCommand = builder.GetUpdateCommand();
adapter.DeleteCommand = builder.GetDeleteCommand();
DataTable dt = new DataTable();
adapter.Fill(dt);
DataRow row = dt.NewRow();
row["RegionID"] = 5;
row["RegionDescription"] = "Some region";
dt.Rows.Add(row);
//dt.AcceptChanges();
int counter = adapter.Update(dt);
}

How to save data from gridcontrol devexpress into oracle database?

I have a GridControl data that I inserted form TextEdit in C#, then I want save those data to oracle database, this my scenario:
private void fmTest_Load(object sender, EventArgs e)
{
dt = new DataTable();
DataColumn dc1 = new DataColumn("NAMA");
DataColumn dc2 = new DataColumn("ALAMAT");
dt.Columns.Add(dc1);
dt.Columns.Add(dc2);
DataRow dr1 = dt.NewRow();
gridControl1.DataSource = dt;
}
This my method to save data from TextEdit to Grid:
public void SimpanGrid()
{
DataRow dr1 = dt.NewRow();
dr1[0] = txtNama.Text;
dr1[1] = txtAlamat.Text;
dt.Rows.Add(dr1);
gridControl1.DataSource = dt;
}
This methode to save data from GridControl but I got still error:
public void SimpanTest()
{
//membuat koneksi_manual
if (koneksi_manual.con.State == ConnectionState.Open)
{
koneksi_manual.con.Close();
}
koneksi_manual.con.Open();
try
{
for (int i = 0; i < gridView1.RowCount - 1; i++)
{
OracleCommand cmd = new OracleCommand();
cmd.CommandText = #"INSERT INTO TEST (NAMA, ALAMAT)
VALUES ('" + gridView1.Columns[i].FieldName.ToString() +
"', '" + gridView1.Columns[i].FieldName.ToString() + "')";
cmd.Connection = koneksi_manual.con;
cmd.ExecuteNonQuery(); //eror disini
MessageBox.Show("DATA TELAH DISIMPAN");
koneksi_manual.con.Close();
}
}
catch (Exception ex)
{
// Memunculkan pesan error
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Then I call that method SimpanTes() in Button Simpan:
private void btnSimpan_Click_1(object sender, EventArgs e)
{
SimpanTest();
}
So, this the problem I couldn't save data to database and I don't know what the correct code must I use.
cmd.CommandText = #"INSERT INTO TEST (NAMA, ALAMAT)
VALUES ('" + gridView1.Columns[i].FieldName.ToString() +
"', '" + gridView1.Columns[i].FieldName.ToString() + "')";
There are several problems in your code. You are closing the connection at the end of your cycle and in the next iteration your getting the error with closed connection. So, you must open your connection before execution of command. Also you need to use GridView.DataRowCount property instead of GridView.RowCount because GridView.RowCount counts visible rows, group rows, new row and filter row. And to get the row cell value you must use GridView.GetRowCellValue method.
Here is example:
if (koneksi_manual.con.State == ConnectionState.Open)
koneksi_manual.con.Close();
for (int i = 0; i < gridView1.DataRowCount - 1; i++)// <= Use gridView1.DataRowCount instead of gridView1.RowCount.
{
OracleCommand cmd = new OracleCommand();
cmd.CommandText = #"INSERT INTO TEST (NAMA, ALAMAT)
VALUES ('" + gridView1.GetRowCellValue(i, "NAMA") +
"', '" + gridView1.GetRowCellValue(i, "ALAMAT") + "')";// <= Use gridView1.GetRowCellValue to get the cell value.
cmd.Connection = koneksi_manual.con;
koneksi_manual.con.Open();// <= Open connection before executing the command.
cmd.ExecuteNonQuery(); //eror disini
MessageBox.Show("DATA TELAH DISIMPAN");
koneksi_manual.con.Close();
}
But also you can use your dt object directly to save values from it:
if (koneksi_manual.con.State == ConnectionState.Open)
koneksi_manual.con.Close();
foreach (DataRow dataRow in dt.Rows)
{
OracleCommand cmd = new OracleCommand();
cmd.CommandText = #"INSERT INTO TEST (NAMA, ALAMAT)
VALUES ('" + dataRow["NAMA"] +
"', '" + dataRow["ALAMAT"] + "')";
cmd.Connection = koneksi_manual.con;
koneksi_manual.con.Open();// <= Open connection before executing the command.
cmd.ExecuteNonQuery(); //eror disini
MessageBox.Show("DATA TELAH DISIMPAN");
koneksi_manual.con.Close();
}

How to insert a data table into SQL Server database table?

I have imported data from some Excel file and I have saved it into a datatable. Now I'd like to save this information in my SQL Server database.
I saw a lot of information on the web but I cannot understand it:
Someone said insert line by line another suggested bulk update... etc: what it better?
Should I use OLE or SQL Server objects (like dataAdapter or connection)?
My need is to read the employee weekly hours report, from his Excel file and save it to a database table where all the reports are saved (updating the db with new records every week).
The Excel file contains reports only for the current week.
Create a User-Defined TableType in your database:
CREATE TYPE [dbo].[MyTableType] AS TABLE(
[Id] int NOT NULL,
[Name] [nvarchar](128) NULL
)
and define a parameter in your Stored Procedure:
CREATE PROCEDURE [dbo].[InsertTable]
#myTableType MyTableType readonly
AS
BEGIN
insert into [dbo].Records select * from #myTableType
END
and send your DataTable directly to sql server:
using (var command = new SqlCommand("InsertTable") {CommandType = CommandType.StoredProcedure})
{
var dt = new DataTable(); //create your own data table
command.Parameters.Add(new SqlParameter("#myTableType", dt));
SqlHelper.Exec(command);
}
To edit the values inside stored-procedure, you can declare a local variable with the same type and insert input table into it:
DECLARE #modifiableTableType MyTableType
INSERT INTO #modifiableTableType SELECT * FROM #myTableType
Then, you can edit #modifiableTableType:
UPDATE #modifiableTableType SET [Name] = 'new value'
If it's the first time for you to save your datatable
Do this (using bulk copy). Assure there are no PK/FK constraint
SqlBulkCopy bulkcopy = new SqlBulkCopy(myConnection);
//I assume you have created the table previously
//Someone else here already showed how
bulkcopy.DestinationTableName = table.TableName;
try
{
bulkcopy.WriteToServer(table);
}
catch(Exception e)
{
messagebox.show(e.message);
}
Now since you already have a basic record. And you just want to check new record with the existing one. You can simply do this.
This will basically take existing table from database
DataTable Table = new DataTable();
SqlConnection Connection = new SqlConnection("ConnectionString");
//I assume you know better what is your connection string
SqlDataAdapter adapter = new SqlDataAdapter("Select * from " + TableName, Connection);
adapter.Fill(Table);
Then pass this table to this function
public DataTable CompareDataTables(DataTable first, DataTable second)
{
first.TableName = "FirstTable";
second.TableName = "SecondTable";
DataTable table = new DataTable("Difference");
try
{
using (DataSet ds = new DataSet())
{
ds.Tables.AddRange(new DataTable[] { first.Copy(), second.Copy() });
DataColumn[] firstcolumns = new DataColumn[ds.Tables[0].Columns.Count];
for (int i = 0; i < firstcolumns.Length; i++)
{
firstcolumns[i] = ds.Tables[0].Columns[i];
}
DataColumn[] secondcolumns = new DataColumn[ds.Table[1].Columns.Count];
for (int i = 0; i < secondcolumns.Length; i++)
{
secondcolumns[i] = ds.Tables[1].Columns[i];
}
DataRelation r = new DataRelation(string.Empty, firstcolumns, secondcolumns, false);
ds.Relations.Add(r);
for (int i = 0; i < first.Columns.Count; i++)
{
table.Columns.Add(first.Columns[i].ColumnName, first.Columns[i].DataType);
}
table.BeginLoadData();
foreach (DataRow parentrow in ds.Tables[0].Rows)
{
DataRow[] childrows = parentrow.GetChildRows(r);
if (childrows == null || childrows.Length == 0)
table.LoadDataRow(parentrow.ItemArray, true);
}
table.EndLoadData();
}
}
catch (Exception ex)
{
throw ex;
}
return table;
}
This will return a new DataTable with the changed rows updated. Please ensure you call the function correctly. The DataTable first is supposed to be the latest.
Then repeat the bulkcopy function all over again with this fresh datatable.
I am giving a very simple code, which i used in my solution (I have the same problem statement as yours)
SqlConnection con = connection string ;
//new SqlConnection("Data Source=.;uid=sa;pwd=sa123;database=Example1");
con.Open();
string sql = "Create Table abcd (";
foreach (DataColumn column in dt.Columns)
{
sql += "[" + column.ColumnName + "] " + "nvarchar(50)" + ",";
}
sql = sql.TrimEnd(new char[] { ',' }) + ")";
SqlCommand cmd = new SqlCommand(sql, con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
cmd.ExecuteNonQuery();
using (var adapter = new SqlDataAdapter("SELECT * FROM abcd", con))
using(var builder = new SqlCommandBuilder(adapter))
{
adapter.InsertCommand = builder.GetInsertCommand();
adapter.Update(dt);
// adapter.Update(ds.Tables[0]); (Incase u have a data-set)
}
con.Close();
I have given a predefined table-name as "abcd" (you must take care that a table by this name doesn't exist in your database).
Please vote my answer if it works for you!!!! :)
I would suggest you go for bulk insert as suggested in this article :
Bulk Insertion of Data Using C# DataTable and SQL server OpenXML function
public bool BulkCopy(ExcelToSqlBo objExcelToSqlBo, DataTable dt, SqlConnection conn, SqlTransaction tx)
{
int check = 0;
bool result = false;
string getInsert = "";
try
{
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
if (dr != null)
{
if (check == 0)
{
getInsert = "INSERT INTO [tblTemp]([firstName],[lastName],[Father],[Mother],[Category]" +
",[sub_1],[sub_LG2])"+
" select '" + dr[0].ToString() + "','" + dr[1].ToString() + "','" + dr[2].ToString() + "','" + dr[3].ToString() + "','" + dr[4].ToString().Trim() + "','" + dr[5].ToString().Trim() + "','" + dr[6].ToString();
check += 1;
}
else
{
getInsert += " UNION ALL ";
getInsert += " select '" + dr[0].ToString() + "','" + dr[1].ToString() + "','" + dr[2].ToString() + "','" + dr[3].ToString() + "','" + dr[4].ToString().Trim() + "','" + dr[5].ToString().Trim() + "','" + dr[6].ToString() ;
check++;
}
}
}
result = common.ExecuteNonQuery(getInsert, DatabasesName, conn, tx);
}
else
{
throw new Exception("No row for insertion");
}
dt.Dispose();
}
catch (Exception ex)
{
dt.Dispose();
throw new Exception("Please attach file in Proper format.");
}
return result;
}
//best way to deal with this is sqlbulkcopy
//but if you dont like it you can do it like this
//read current sql table in an adapter
//add rows of datatable , I have mentioned a simple way of it
//and finally updating changes
Dim cnn As New SqlConnection("connection string")
cnn.Open()
Dim cmd As New SqlCommand("select * from sql_server_table", cnn)
Dim da As New SqlDataAdapter(cmd)
Dim ds As New DataSet()
da.Fill(ds, "sql_server_table")
Dim cb As New SqlCommandBuilder(da)
//for each datatable row
ds.Tables("sql_server_table").Rows.Add(COl1, COl2)
da.Update(ds, "sql_server_table")
I found that it was better to add to the table row by row if your table has a primary key. Inserting the entire table at once creates a conflict on the auto increment.
Here's my stored Proc
CREATE PROCEDURE dbo.usp_InsertRowsIntoTable
#Year int,
#TeamName nvarchar(50),
AS
INSERT INTO [dbo.TeamOverview]
(Year,TeamName)
VALUES (#Year, #TeamName);
RETURN
I put this code in a loop for every row that I need to add to my table:
insertRowbyRowIntoTable(Convert.ToInt16(ddlChooseYear.SelectedValue), name);
And here is my Data Access Layer code:
public void insertRowbyRowIntoTable(int ddlValue, string name)
{
SqlConnection cnTemp = null;
string spName = null;
SqlCommand sqlCmdInsert = null;
try
{
cnTemp = helper.GetConnection();
using (SqlConnection connection = cnTemp)
{
if (cnTemp.State != ConnectionState.Open)
cnTemp.Open();
using (sqlCmdInsert = new SqlCommand(spName, cnTemp))
{
spName = "dbo.usp_InsertRowsIntoOverview";
sqlCmdInsert = new SqlCommand(spName, cnTemp);
sqlCmdInsert.CommandType = CommandType.StoredProcedure;
sqlCmdInsert.Parameters.AddWithValue("#Year", ddlValue);
sqlCmdInsert.Parameters.AddWithValue("#TeamName", name);
sqlCmdInsert.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (sqlCmdInsert != null)
sqlCmdInsert.Dispose();
if (cnTemp.State == ConnectionState.Open)
cnTemp.Close();
}
}
From my understanding of the question,this can use a fairly straight forward solution.Anyway below is the method i propose ,this method takes in a data table and then using SQL statements to insert into a table in the database.Please mind that my solution is using MySQLConnection and MySqlCommand replace it with SqlConnection and SqlCommand.
public void InsertTableIntoDB_CreditLimitSimple(System.Data.DataTable tblFormat)
{
for (int i = 0; i < tblFormat.Rows.Count; i++)
{
String InsertQuery = string.Empty;
InsertQuery = "INSERT INTO customercredit " +
"(ACCOUNT_CODE,NAME,CURRENCY,CREDIT_LIMIT) " +
"VALUES ('" + tblFormat.Rows[i]["AccountCode"].ToString() + "','" + tblFormat.Rows[i]["Name"].ToString() + "','" + tblFormat.Rows[i]["Currency"].ToString() + "','" + tblFormat.Rows[i]["CreditLimit"].ToString() + "')";
using (MySqlConnection destinationConnection = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
using (var dbcm = new MySqlCommand(InsertQuery, destinationConnection))
{
destinationConnection.Open();
dbcm.ExecuteNonQuery();
}
}
}//CreditLimit

Categories