Can't write to SQLite database in WPF project - c#

Having one of those tear-your-hair-out evenings.
I'm porting a WPF project over from using access and OleDBConnection to using SQLite and SQLiteConnection. My application reads from the project upon load, and then writes to it later after some form entry.
The reading works fine, using this code:
private void InitialiseDB()
{
connString = "data source = PortalDB.db";
conn = new SQLiteConnection(connString);
SQLiteCommand AttendeeCmd = new SQLiteCommand("SELECT * FROM AttendeeNames", conn);
SQLiteCommand SignInOutsCmd = new SQLiteCommand("SELECT SignTime, UserID, SignType FROM SignInOuts", conn);
conn.Open();
SQLiteDataAdapter AttendeeAdapter = new SQLiteDataAdapter(AttendeeCmd);
SQLiteDataAdapter SignInOutsAdapter = new SQLiteDataAdapter(SignInOutsCmd);
//Clear current datatables
AttendeeNamesTable.Clear();
SignInOutsTable.Clear();
//Fill data tables from adapters
AttendeeAdapter.Fill(AttendeeNamesTable);
SignInOutsAdapter.Fill(SignInOutsTable);
conn.Close();
}
But for the life of me I can't get the writing to work, It doesn't throw any errors or exceptions, it just doesn't write to the database. That code looks like this, with the data being passed in from having just been aded to a local DataTable:
private void SyncUpDB(int SignUserId, string SignType, DateTime SignTime)
{
//...Open the connection...
conn.Open();
//..Make SQL query by declaring fields to write to (not SignID) and where to get the data from. Strings need single quote, numbers do not.
String SyncUpDBQuery = "INSERT INTO SignInOuts (SignTime,UserID,SignType) VALUES('" + SignTime + "', " + SignUserId + ", '" + SignType + "')";
//...Make new database command from query
SQLiteCommand SyncUpDBCommand = new SQLiteCommand(SyncUpDBQuery, conn);
//...And execute on database
SyncUpDBCommand.ExecuteNonQuery();
}
As I say, this used to work perfectly with Access, just won't play ball with SQLite... any ideas?

Related

POS system SQL query for cart display C#

I am developing a POS system for a stationary. I am currently stuck in the sales page. I want to add to data grid view a product when user inputs barcode, quantity, discount and client id and this is the error I am getting:
System.Data.SqlClient.SqlException: 'Incorrect syntax near the keyword 'transaction'
string query;
string query2;
using (SqlConnection sqlcon2 = new SqlConnection(cons))
{
query = "insert into dbo.transaction set (qte,remise,idclt) values ('" + textBox4.Text + "','" + comboBox1.Text + "','" + textBox6.Text + "')";
SqlDataAdapter sda = new SqlDataAdapter(query, sqlcon2);
}
using (SqlConnection sqlcon = new SqlConnection(cons))
{
sqlcon.Open();
query2 = "select produit.idprod, produit.nom_produit, transaction.qte, transaction.remise, transaction.idclt, transaction.qte*produit.prixV as Total from [dbo].[produit] join [dbo].[transaction] on produit.idprod=transaction.idprod join [dbo].[clients] clt on clt.idclt=transaction.idclt where produit.idprod= '" + textBox4.Text+"' and transaction.qte='"+textBox5.Text+"'";
SqlDataAdapter sda2 = new SqlDataAdapter(query2, sqlcon);
DataTable dt = new DataTable();
sda2.Fill(dt);
dgv.DataSource = dt;
}
Database Schema:
Form Design:
Hello and welcome to Stack Overflow.
It's highly likely that the problem in your code is the table's name being transaction, a keyword in the RDBMS you are using (as evidenced by the exception's message). Try to change it to something else.
In addition, your snippet is vulnerable to an SQL injection attack. Unless your project is well into development, you should consider using an ORM framework like Entity Framework Core.

How to use local db project work on different pc

I have been trying to use local db of c# and I have managed to work with local db. My db contains a connection string which is used by this command
SqlConnection _connection = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=F:\Devjeet Projects\Visual Studio Projects\Pujo Project\FinalPujoSetup\FinalPujoSetup\counter_db.mdf;Integrated Security=True");
I can see the path of the connection string contains the path somewhere in my pc. I am able to access the data with these queries.
For updating the database
_connection.Open();
SqlCommand cmd = _connection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "update [Table] set Time = '" + _new_time + "'";
cmd.ExecuteNonQuery();
_connection.Close();
and for fetching the data.
_connection.Open();
String sqlSelectQuery = "SELECT * FROM [Table] WHERE Id = " + int.Parse("1");
SqlCommand cmd = new SqlCommand(sqlSelectQuery, _connection);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
lblTotalTime.Text = (dr["Time"].ToString());
}
_connection.Close();
In this line lblTotalTime.Text = (dr["Time"].ToString()); the Time is the only table data.
Now I want to transfer this project to my friends pc and run it there. Obviously, it will not work because the path will be different.
is there any way I can change the connection string such that it can automatically fetch the path of the database in any computer and then can be executed there?
or is there any other way that I could use local db such that when I transfer the application in different pc, my application will work?

decrypt values in sqlite database and view them on datagrid

am new to wpf and am having a bit of trouble on how to decrypt an a encrypted values in my db to view on a datagrid , i have been searching for a solution for almost 2 days and only came up with this code
//private static String Encrypt(string Text)
//private static String Decrypt(string Text)
private void refresh_datagrid()
{
//create temp directory
var tempdir = Path.GetFullPath(Path.Combine(Path.GetTempPath(),Guid.NewGuid().ToString()));
Directory.CreateDirectory(tempdir);
//create temp db with same table and details same as on original db
SQLiteConnection.CreateFile(tempdir+"tempdb.sqlite;security=true;");
var con1 = new SQLiteConnection("Data
Source="+tempdir+"\\tempdb.sqlite;");
con1.Open();
con1.ChangePassword(defaultpassword);
String sql = "CREATE TABLE acc (nam STRING, pas STRING)";
SQLiteCommand command = new SQLiteCommand(sql, con1);
command.ExecuteNonQuery();
//open a connection to encrypted db
using (var con2 = new SQLiteConnection("DataSource="+db_path+";security=true;"))
{
con2.Open();
con2.ChangePassword(defaultpassword);
SQLiteCommand cmd = con2.CreateCommand();
cmd.CommandText = "SELECT * FROM acc ";
//read encrypted strings to decrypt it then pass them to tempdb
SQLiteDataReader reader;
reader = cmd.ExecuteReader();
while(reader.Read())
{
SQLiteCommand cmdc = con1.CreateCommand();
cmdc.CommandText = "INSERT INTO acc (nam,pas) VALUES (#username ,#password )";
cmdc.Parameters.AddWithValue("#username", Decrypt(reader["nam"].ToString()));
cmdc.Parameters.AddWithValue("#password", Decrypt(reader["pas"].ToString()));
cmdc.ExecuteNonQuery();
}
//view tempdb data on datagrid
SQLiteDataAdapter dataAdapter = new SQLiteDataAdapter(cmd.CommandText, con1);
DataTable dataTable = new DataTable();
dataAdapter.Fill(dataTable);
control.ItemsSource = dataTable.AsDataView();
con1.Close();
con2.Close();
//remove tempdir and tempdb
Directory.Delete(tempdir,true);
}
}
it works but this is just a simplified code.
on my full code i have more tables with 6 more details and 120 accounts
and when i try to view them on my datagrid the app hangs for 3-4 seconds i went around this problem with backgroundworker
but still not satisfied with the delay i need a better way to handle this any help is appreciated.
ps: sorry about any wrong grammar or spelling EN is not my home language
Try to add logs in between lines to find out the bottle neck
Read all the records to memory from encrypted db first instead of writing while reading
How many rows are there in the db? Do you join all of the 6 tables in your query? Consider sql tuning

insert,update in single button clickin winforms

I am not getting, how to do insert and update of the data in C# WinForms on single button click.
private void save_Click(object sender, EventArgs e)
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = "data source=Sai;database=kaur; user id=sa;password=azxc;";
cn.Open();
string gen;
if (radioButton1.Checked == true)
gen = "Male";
else
gen = "Female";
string clas = null;
clas = comboBox1.Text;
string section = null;
section = comboBox2.Text;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "insert into studetail values('" + textBox1.Text + "','" + textBox2.Text + "','" + gen + "','" + textBox3.Text + "','" + clas + "','" + section + "')";
cmd.Connection = cn;
int n = cmd.ExecuteNonQuery();
if (n > 0)
MessageBox.Show(n + " Row Inserted.");
else
MessageBox.Show("Insertion failed.");
SqlDataAdapter da = new SqlDataAdapter("select * from studetail ", cn);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
You can add a deletion before the insertion:
private void save_Click(object sender, EventArgs e)
{
DeletePerson(id); // add this
SqlConnection cn = new SqlConnection();
...
}
public void DeletePerson(int id)
{
using(SqlConnection connection = new SqlConnection(credentials))
{
connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = "delete from studetail where someUniqeIdColumn = " + id;
cmd.ExecuteNonQuery();
}
}
Using responsible to dispose the connection.
Consider using Entity Framework or LINQ to SQL.
You are exposed to SQL injection.
First off the SQL query isn't quite right. It should look something like the following:
INSERT INTO studetail (columnName1, columnName2, ...columnNameN)
VALUES (value1, value2, ...valueN);
Where the column names are the columns where you want data to be inserted, and the values are the data you want inserted into said columns.
You should also be disposing the connection by wrapping the connection within a using statement.
using(var con = new SqlConnection(connectionString))
{
con.Open();
//rest of code that needs a connection here
}
Additionally, you need to be wary of SQL injection. I highly suggest reading this example from the MSDN website. It will give you an example of using an SQL Update and avoiding SQL injection with use of SqlCommand.Paramaters property.
You should also have a Primary Key in your database tables, if you don't already, so you can uniquely identify each record in a table.
To do an update and a save on the same button, you will need to check if a row already exists for the data that is being edited. This when a Primary comes in handy. You will want to check your database to see if a record already exists
SELECT 1 FROM studetail WHERE <Condition>
The WHERE condition will be the way you uniquely identify (a Primary Key) a row in your table. If the rows in the table are uniquely identified, the above SQL statement will return 1 if a value exists, which means you can UPDATE or 0 if no record exists, so you can INSERT

How to run a SQL query command for Access from another SQL query command?

The problem is that I need to Execute a SQL command for a query on Access which I already have running perfectly.
using (OleDbConnection _Connn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Pos\POS_DB(" + _DS.sNumCaja + ").accdb"))
sSQL =
"SELECT Sum(tblVentasArticulos.Cantidad) AS SumOfCantidad, Sum(tblVentasArticulos.Precio) AS SumOfPrecio, qryDepartamentos.Departamento" + " " +
"FROM qryDepartamentos RIGHT JOIN (tblVentasArticulos RIGHT JOIN tblVentas ON tblVentasArticulos.Folio = tblVentas.Folio) ON qryDepartamentos.idDepartamento = tblVentasArticulos.Dep" + " " +
"GROUP BY qryDepartamentos.Departamento;";
OleDbCommand cmd = new OleDbCommand(sSQL, _Connn);
That piece of code works well, but inside the sSQL string, the "qryDepartamentos" is a query I made inside Access from a table on another Access DataBase. Is there a way of making the Query before and storing it inside a DataSet to use it as a variable for another SQL command? I tried something like this:
DataTable results = new DataTable();
OleDbDataAdapter adapter;
using (OleDbConnection conn = new OleDbConnection(connString))
{
OleDbCommand cmd = new OleDbCommand("SELECT tblDepartamentos.* FROM tblDepartamentos", conn);
conn.Open();
adapter = new OleDbDataAdapter(cmd);
adapter.Fill(results);
DataView dv = new DataView(results);
}
Now I don't know how to add or use the DataSet data inside the first sSQL command, in order to replace the "qryDepartamentos".
Thank you but I figured it'd be easier to use a function and giving the parameters so it would return a simple string. Thank You All! :)

Categories