Writing changes to a SQLite database using SqliteDataAdapter - c#

What am I missing from the following code? In this code fragment, I am reading in a table from a SQLite database. I am then updating a cell, and then reading back the change.
This code is a simplified version of larger code, but it illustrates the problem.
The code reads the table perfectly, however AcceptChanges() does not write anything back. I verified that with the repeated read and by going to SQLiteAdmin and perusing the table.
I tried adding the "oLocalAdapter.Update(oLocalSet.Tables[0]);" line, however that did not make any difference. I saw that doing a search.
using System.Data.SQLite;
// DATABASE (Local): Formulate the SQL command.
String strSqlCommand = "SELECT * FROM [tblTest] ORDER BY [IdPrimary] ASC;";
SQLiteCommand oLocalCommand = new SQLiteCommand(strSqlCommand, ClassEngine.Connection);
// DATABASE (Local): Get the data records.
SQLiteDataAdapter oLocalAdapter = new SQLiteDataAdapter(oLocalCommand);
DataSet oLocalSet = new DataSet();
oLocalAdapter.Fill(oLocalSet, "tblTest");
// Try to write to some changes.
String strValue = oLocalSet.Tables[0].Rows[0][8].ToString();
oLocalSet.Tables[0].Rows[0][8] = 9;
oLocalSet.Tables[0].AcceptChanges();
oLocalAdapter.Update(oLocalSet.Tables[0]);
// Clean up.
oLocalSet.Dispose();
oLocalAdapter.Dispose();
oLocalCommand.Dispose();
oLocalCommand = null;

Okay, got it.
One, I had to relocate/modify the AcceptChanges() line.
That includes the possible line
oLocalAdapter.AcceptChangesDuringUpdate = true;
I then had to add in
SQLiteCommandBuilder oBuilder = new SQLiteCommandBuilder(oLocalAdapter);
oLocalAdapter.UpdateCommand = oBuilder.GetUpdateCommand();
The last line is then the update and it works. That makes the code:
// DATABASE (Local): Formulate the SQL command.
String strSqlCommand = "SELECT * FROM tblTest ORDER BY IdPrimary ASC;";
SQLiteCommand oLocalCommand = new SQLiteCommand(strSqlCommand, ClassEngine.Connection);
// DATABASE (Local): Get the data records.
SQLiteDataAdapter oLocalAdapter = new SQLiteDataAdapter(oLocalCommand);
DataSet oLocalSet = new DataSet();
oLocalAdapter.Fill(oLocalSet, "tblTest");
//
SQLiteCommandBuilder oBuilder = new SQLiteCommandBuilder(oLocalAdapter);
// Try to write to some changes.
String strValue = oLocalSet.Tables[0].Rows[0][8].ToString();
oLocalSet.Tables[0].Rows[0][8] = 9;
strValue = oLocalSet.Tables[0].Rows[0][8].ToString();
oLocalSet.AcceptChanges();
oLocalAdapter.UpdateCommand = oBuilder.GetUpdateCommand();
oLocalAdapter.Update(oLocalSet.Tables[0]);
// Clean up.
oLocalSet.Dispose();
oLocalAdapter.Dispose();
oLocalCommand.Dispose();
oLocalCommand = null;

public void SaveDataTable(DataTable DT)
{
try
{
con.Open();
cmd = con.CreateCommand();
cmd.CommandText = string.Format("SELECT * FROM {0}", DT.TableName);
adapter = new SQLiteDataAdapter(cmd);
SQLiteCommandBuilder builder = new SQLiteCommandBuilder(adapter);
adapter.Update(DT);
con.Close();
}
catch (Exception Ex)
{
System.Windows.MessageBox.Show(Ex.Message);
}

Related

Proper way of closing Oracle table update - C# . NET

I follow below steps to update an oracle table:
First calculate observable collection; property indicating a column. Display this information in a WPF datagrid. I save this information to the Oracle database. This seems to work fine.
While the grid is open, I change the some cell values. I re-saved the modified values to the table. This also works fine.
I try to get updated/modified values to perform some other calculation. I noticed that my program still used the initially saved values; it didnt pick modified values even though database shows correct values. Does is happen because I am not committing / closing the Oracle connection properly?
Here is my code to save the data into Oracle table:
using (OracleConnection thisConnection = new OracleConnection(connectionname))
{
string query = "INSERT INTO TEST(WellBore,PDate, Pressure,Temperature)VALUES(:WellBore,:PDate,:Pressure,:Temperature)";
OracleCommand myAccessCommand = new OracleCommand(query, thisConnection);
var sdate = Datetime.Now.Date.ToShortDateString();
myAccessCommand.Parameters.Add("WellBore", OracleDbType.NVarchar2, 20).Value = “ABC”;
myAccessCommand.Parameters.Add("PDate", DateTime.Parse(sdate));
myAccessCommand.Parameters.Add("Pressure", OracleDbType.Decimal).Value = 1000;
myAccessCommand.Parameters.Add("Temperature ", OracleDbType.Decimal).Value = 50;
thisConnection.Open();
myAccessCommand.ExecuteNonQuery();
thisConnection.Dispose();
}
So I believe my question how do I commit the connection?
Here's an example using an insert statement with a transaction. It also grabs a returned id value, which may not be needed in your case, but anyway:
int event_id = 0;
using (OracleConnection oraConn = new OracleConnection(connStr))
{
string cmdText = #"insert into EVENT
(EVENT_NAME, EVENT_DESC)
values
(:EVENT_NAME, :EVENT_DESC)
RETURNING EVENT_ID INTO :EVENT_ID
";
using (OracleCommand cmd = new OracleCommand(cmdText, oraConn))
{
oraConn.Open();
OracleTransaction trans = oraConn.BeginTransaction();
try
{
OracleParameter prm = new OracleParameter();
cmd.BindByName = true;
prm = new OracleParameter("EVENT_NAME", OracleDbType.Varchar2); prm.Value = "SOME NAME"; cmd.Parameters.Add(prm);
prm = new OracleParameter("EVENT_DESC", OracleDbType.Varchar2); prm.Value = "SOME DESC"; cmd.Parameters.Add(prm);
prm = new OracleParameter("EVENT_ID", OracleDbType.Int32, ParameterDirection.ReturnValue); cmd.Parameters.Add(prm);
cmd.ExecuteNonQuery();
trans.Commit();
// return value
event_id = ConvertFromDB<int>(cmd.Parameters["EVENT_ID"].Value);
}
catch
{
trans.Rollback();
throw;
}
finally
{
trans.Dispose();
}
oraConn.Close();
}
}
Note: The "ConvertFromDB" is just a generic to cast the return value to its .NET equivalent (an int in this case). Again, if you aren't capturing a returned value, you don't need to worry about it.

Bulk copy a DataTable into MySQL (similar to System.Data.SqlClient.SqlBulkCopy)

I am migrating my program from Microsoft SQL Server to MySQL. Everything works well except one issue with bulk copy.
In the solution with MS SQL the code looks like this:
connection.Open();
SqlBulkCopy bulkCopy = new SqlBulkCopy(connection);
bulkCopy.DestinationTableName = "testTable";
bulkCopy.WriteToServer(rawData);
Now I try to do something similar for MySQL. Because I think there would be bad performance I don't want to write the DataTable to a CSV file and do the insert from there with the MySqlBulkLoader class.
Any help would be highly appreciated.
Because I think there would be bad performance I don't want to write the DataTable to a CSV file and do the insert from there with the MySqlBulkLoader class.
Don't rule out a possible solution based on unfounded assumptions. I just tested the insertion of 100,000 rows from a System.Data.DataTable into a MySQL table using a standard MySqlDataAdapter#Update() inside a Transaction. It consistently took about 30 seconds to run:
using (MySqlTransaction tran = conn.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.Connection = conn;
cmd.Transaction = tran;
cmd.CommandText = "SELECT * FROM testtable";
using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
{
da.UpdateBatchSize = 1000;
using (MySqlCommandBuilder cb = new MySqlCommandBuilder(da))
{
da.Update(rawData);
tran.Commit();
}
}
}
}
(I tried a couple of different values for UpdateBatchSize but they didn't seem to have a significant impact on the elapsed time.)
By contrast, the following code using MySqlBulkLoader took only 5 or 6 seconds to run ...
string tempCsvFileSpec = #"C:\Users\Gord\Desktop\dump.csv";
using (StreamWriter writer = new StreamWriter(tempCsvFileSpec))
{
Rfc4180Writer.WriteDataTable(rawData, writer, false);
}
var msbl = new MySqlBulkLoader(conn);
msbl.TableName = "testtable";
msbl.FileName = tempCsvFileSpec;
msbl.FieldTerminator = ",";
msbl.FieldQuotationCharacter = '"';
msbl.Load();
System.IO.File.Delete(tempCsvFileSpec);
... including the time to dump the 100,000 rows from the DataTable to a temporary CSV file (using code similar to this), bulk-loading from that file, and deleting the file afterwards.
Similar to SqlBulkCopy, we have MySqlBulkCopy for Mysql.
here is the example how to use it.
public async Task<bool> MySqlBulCopyAsync(DataTable dataTable)
{
try
{
bool result = true;
using (var connection = new MySqlConnector.MySqlConnection(_connString + ";AllowLoadLocalInfile=True"))
{
await connection.OpenAsync();
var bulkCopy = new MySqlBulkCopy(connection);
bulkCopy.DestinationTableName = "yourtable";
// the column mapping is required if you have a identity column in the table
bulkCopy.ColumnMappings.AddRange(GetMySqlColumnMapping(dataTable));
await bulkCopy.WriteToServerAsync(dataTable);
return result;
}
}
catch (Exception ex)
{
throw;
}
}
private List<MySqlBulkCopyColumnMapping> GetMySqlColumnMapping(DataTable dataTable)
{
List<MySqlBulkCopyColumnMapping> colMappings = new List<MySqlBulkCopyColumnMapping>();
int i = 0;
foreach (DataColumn col in dataTable.Columns)
{
colMappings.Add(new MySqlBulkCopyColumnMapping(i, col.ColumnName));
i++;
}
return colMappings;
}
You can ignore the column mapping if you don't have any identity column in your table.
If you have identity column then you have to use the column mapping otherwise it won't insert any records in the table
It will just give message like "x rows were copied but only 0 rows were inserted".
This class i available in the below library
Assembly MySqlConnector, Version=1.0.0.0
Using any of BulkOperation NuGet-package, you can easily have this done.
Here is an example using the package from https://www.nuget.org/packages/Z.BulkOperations/2.14.3/
MySqlConnection conn = DbConnection.OpenConnection();
DataTable dt = new DataTable("testtable");
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM testtable", conn);
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
da.Fill(dt);
instead of using
......
da.UpdateBatchSize = 1000;
......
da.Update(dt)
just following two lines
var bulk = new BulkOperation(conn);
bulk.BulkInsert(dt);
will take only 5 seconds to copy the whole DataTable into MySQL without first dumping the 100,000 rows from the DataTable to a temporary CSV file.

C# and SQLCE Database Not Updating

Ok, I have been having a problem the last few days with my database not updating. I can read the data fine and I'm not getting any exceptions either. I'm trying to update the database then I try to read values again after the update (during same run), and they still hold the original values, so it doesn't seem to be an issue with the database being copied to another folder (I'm using Copy if newer yet neither database is being updated).
Here is the code I'm using. As you can see I tried a few different approaches, none of which worked yet.
public void UpdateDatabaseInStock(string itemName, string tableName)
{
DataSet data = new DataSet("Items");
int val;
//get the file path to the database as a string
string dbfile =
new System.IO.FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).DirectoryName +
"\\Database\\GameData.sdf";
//connect to the database
using (SqlCeConnection cntn = new SqlCeConnection("datasource=" + dbfile))
{
//create an adapter to pull all data from the table
using (SqlCeDataAdapter adpt = new SqlCeDataAdapter
("SELECT * FROM " + tableName + " WHERE Name LIKE '%" + itemName + "%'", cntn))
{
//put the data into a DataSet
adpt.Fill(data);
cntn.Close();
}
//fill the data from the Items table into a DataTable to return.
DataTable itemTable = data.Tables[0];
DataRow a = itemTable.Rows[0];
val = (short)a.ItemArray[3] - 1;
dbfile = "";
data.Dispose();
itemTable.Dispose();
SqlCeCommand cmd = new SqlCeCommand();
cmd.Connection = cntn;
cntn.Open();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "UPDATE " + tableName + " SET [In Stock] = #Value WHERE [Name] = '#ItemName'";
//cmd.Parameters.Add("#Value", SqlDbType.SmallInt);
//cmd.Parameters["#Value"].Value = val;
//cmd.Parameters.Add("#ItemName", SqlDbType.NChar, 75);
//cmd.Parameters["#ItemName"].Value = itemName;
cmd.Parameters.AddWithValue("#Value", val);
cmd.Parameters.AddWithValue("#ItemName", itemName);
cmd.ExecuteNonQuery();
//close the conenction
cntn.Close();
cmd.Dispose();
}
}
Any ideas to get it to actually update?
Just a hunch (can't corroborate this on msdn): could it be that using nchar(75) adds spaces to the parameter, thereby causing the WHERE clause to fail?

Filling a DataTable in C# using MySQL

I'm attempting to fill a DataTable with results pulled from a MySQL database, however the DataTable, although it is initialised, doesn't populate. I wanted to use this DataTable to fill a ListView. Here's what I've got for the setting of the DataTable:
public DataTable SelectCharacters(string loginName)
{
this.Initialise();
string connection = "0.0.0.0";
string query = "SELECT * FROM characters WHERE _SteamName = '" + loginName + "'";
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataAdapter returnVal = new MySqlDataAdapter(query,connection);
DataTable dt = new DataTable("CharacterInfo");
returnVal.Fill(dt);
this.CloseConnection();
return dt;
}
else
{
this.CloseConnection();
DataTable dt = new DataTable("CharacterInfo");
return dt;
}
}
And for the filling of the ListView, I've got:
private void button1_Click(object sender, EventArgs e)
{
string searchCriteria = textBox1.Text;
dt = characterDatabase.SelectCharacters(searchCriteria);
MessageBox.Show(dt.ToString());
listView1.View = View.Details;
ListViewItem iItem;
foreach (DataRow row in dt.Rows)
{
iItem = new ListViewItem();
for (int i = 0; i < row.ItemArray.Length; i++)
{
if (i == 0)
iItem.Text = row.ItemArray[i].ToString();
else
iItem.SubItems.Add(row.ItemArray[i].ToString());
}
listView1.Items.Add(iItem);
}
}
Is there something I'm missing? The MessageBox was included so I could see if it has populated, to no luck.
Thanks for any help you can give.
Check your connection string and instead of using
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataAdapter returnVal = new MySqlDataAdapter(query,connection);
DataTable dt = new DataTable("CharacterInfo");
returnVal.Fill(dt);
this.CloseConnection();
return dt;
you can use this one
MySqlCommand cmd = new MySqlCommand(query, connection);
DataTable dt = new DataTable();
dt.load(cmd.ExecuteReader());
return dt;
Well, I ... can't figure out what you have done here so I'll paste you my code with which I'm filling datagridview:
1) Connection should look something like this(if localhost is your server, else, IP adress of server machine):
string connection = #"server=localhost;uid=root;password=*******;database=*******;port=3306;charset=utf8";
2) Query is ok(it will return you something), but you shouldn't build SQL statements like that.. use parameters instead. See SQL injection.
3) Code:
void SelectAllFrom(string query, DataGridView dgv)
{
_dataTable.Clear();
try
{
_conn = new MySqlConnection(connection);
_conn.Open();
_cmd = new MySqlCommand
{
Connection = _conn,
CommandText = query
};
_cmd.ExecuteNonQuery();
_da = new MySqlDataAdapter(_cmd);
_da.Fill(_dataTable);
_cb = new MySqlCommandBuilder(_da);
dgv.DataSource = _dataTable;
dgv.DataMember = _dataTable.TableName;
dgv.AutoResizeColumns();
_conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (_conn != null) _conn.Close();
}
}
So, every time I want to display some content of table in mysql database I call this method, pass query string and datagridview name to that method. and, that is it.
For your sake, compare this example with your and see what can you use from both of it. Maybe, listview is not the best thing for you, just saying ...
hope that this will help you a little bit.
Debug your application and see if your sql statement/ connection string is correct and returns some value, also verify if your application is not throwing any exception.
Your connection string is invalid.
Set it as follows:
connection = "Server=myServer;Database=myDataBase;Uid=myUser;Pwd=myPassword;";
Refer: mysql connection strings
Here the following why the codes would not work.
Connection
The connection of your mySQL is invalid
Query
I guess do you want to search in the table, try this query
string query = "SELECT * FROM characters WHERE _SteamName LIKE '" + loginName + "%'";
notice the LIKE and % this could help to list all the data. for more details String Comparison Functions

SQLite, Copy DataSet / DataTable to DataBase file

I have filled a DataSet with a Table that was created from another database file. The table is NOT in the database file which I want to be able to copy the Table to.
Now I want to save all those records (DataTable) to a newly created SQLite database file...
How can i do that?
Also I really want to avoid loops if this is possible.
The best answer is by me :) so i'll share it.This is loop but writes 100k entries in 2-3secs.
using (DbTransaction dbTrans = kaupykliuduomConn.BeginTransaction())
{
downloadas.Visible = true; //my progressbar
downloadas.Maximum = dataSet1.Tables["duomenys"].Rows.Count;
using (DbCommand cmd = kaupykliuduomConn.CreateCommand())
{
cmd.CommandText = "INSERT INTO duomenys(Barkodas, Preke, kiekis) VALUES(?,?,?)";
DbParameter Field1 = cmd.CreateParameter();
DbParameter Field2 = cmd.CreateParameter();
DbParameter Field3 = cmd.CreateParameter();
cmd.Parameters.Add(Field1);
cmd.Parameters.Add(Field2);
cmd.Parameters.Add(Field3);
while (n != dataSet1.Tables["duomenys"].Rows.Count)
{
Field1.Value = dataSet1.Tables["duomenys"].Rows[n]["Barkodas"].ToString();
Field2.Value = dataSet1.Tables["duomenys"].Rows[n]["Preke"].ToString();
Field3.Value = dataSet1.Tables["duomenys"].Rows[n]["kiekis"].ToString();
downloadas.Value = n;
n++;
cmd.ExecuteNonQuery();
}
}
dbTrans.Commit();
}
In this case dataSet1.Tables["duomenys"] is already filled with all the data i need to transfer to another database. I used loop to fill dataset too.
When you load the DataTable from the source database, set the AcceptChangesDuringFill property of the data adapter to false, so that loaded records are kept in the Added state (assuming that the source database is SQL Server)
var sqlAdapter = new SqlDataAdapter("SELECT * FROM the_table", sqlConnection);
DataTable table = new DataTable();
sqlAdapter.AcceptChangesDuringFill = false;
sqlAdapter.Fill(table);
Create the table in the SQLite database, by executing the CREATE TABLE statement directly with SQLiteCommand.ExecuteNonQuery
Create a new DataAdapter for the SQLite database connection, and use it to Update the db:
var sqliteAdapter = new SQLiteDataAdapter("SELECT * FROM the_table", sqliteConnection);
var cmdBuilder = new SQLiteCommandBuilder(sqliteAdapter);
sqliteAdapter.Update(table);
If the source and target tables have the same column names and compatible types, it should work fine...
The way to import SQL data to SQLite will take long time. When you want to import data in millions, It will take lot of time. So the shortest and easiest way to do that is just fill fetch the data from SQL database in a DataTable and insert all its rows to SQLite database.
public bool ImportDataToSQLiteDatabase(string Proc, string SQLiteDatabase, params object[] obj)
{
DataTable result = null;
SqlConnection conn = null;
SqlCommand cmd = null;
try
{
result = new DataTable();
using (conn = new SqlConnection(ConStr))
{
using (cmd = CreateCommand(Proc, CommandType.StoredProcedure, obj))
{
cmd.Connection = conn;
conn.Open();
result.Load(cmd.ExecuteReader());
}
}
using (SQLiteConnection con = new SQLiteConnection(string.Format("Data Source={0};Version=3;New=False;Compress=True;Max Pool Size=100;", SQLiteDatabase)))
{
con.Open();
using (SQLiteTransaction transaction = con.BeginTransaction())
{
foreach (DataRow row in result.Rows)
{
using (SQLiteCommand sqlitecommand = new SQLiteCommand("insert into table(fh,ch,mt,pn) values ('" + Convert.ToString(row[0]) + "','" + Convert.ToString(row[1]) + "','"
+ Convert.ToString(row[2]) + "','" + Convert.ToString(row[3]) + "')", con))
{
sqlitecommand.ExecuteNonQuery();
}
}
transaction.Commit();
new General().WriteApplicationLog("Data successfully imported.");
return true;
}
}
}
catch (Exception ex)
{
result = null;
return false;
}
finally
{
if (conn.State == ConnectionState.Open)
conn.Close();
}
}
It will take a very few time as compare to upper given answers.

Categories

Resources