I have a constructor that takes data from a SQL Server database and puts it in a local SQLite database:
public ForemanController()
{
connectionString.DataSource = "dxdb02v";
connectionString.InitialCatalog = "QTRAX4619410";
connectionString.UserID = "tunnelld";
connectionString.Password = "david";
string queryString = "SELECT * FROM [QTRAXAdmin].[vwQT_Foreman]";
List<Foreman> list;
// Creates a SQL connection
using (var connection = new SqlConnection(connectionString.ToString()))
{
using (var command = new SqlCommand(queryString, connection))
{
connection.Open();
using (var reader = command.ExecuteReader())
{
list = new List<Foreman>();
while (reader.Read())
{
list.Add(new Foreman { ForeBadge = reader.GetString(0), ForeName = reader.GetString(1) });
}
}
}
connection.Close();
allForeman = list.ToArray();
}
string deleteSQL = "DELETE FROM Foreman;";
using (SQLiteConnection SQLconn1 = new SQLiteConnection(SQLiteConnectionString))
{
using (var command = new SQLiteCommand(deleteSQL, SQLconn1))
{
command.Connection.Open();
command.ExecuteNonQuery();
}
}
using (SQLiteConnection SQLconn2 = new SQLiteConnection(SQLiteConnectionString))
{
SQLiteCommand cmd2 = SQLconn2.CreateCommand();
foreach (Foreman row in allForeman)
{
cmd2.CommandText = "INSERT INTO Foreman (ForeBadge, ForeName) VALUES (#param1, #param2);";
cmd2.Parameters.Add(new SQLiteParameter("#param1", row.ForeBadge));
cmd2.Parameters.Add(new SQLiteParameter("#param2", row.ForeName));
cmd2.ExecuteNonQuery();
}
}
}
Everything seems to be working fine until the last using statement:
using (SQLiteConnection SQLconn2 = new SQLiteConnection(SQLiteConnectionString))
{
SQLiteCommand cmd2 = SQLconn2.CreateCommand();
foreach (Foreman row in allForeman)
{
cmd2.CommandText = "INSERT INTO Foreman (ForeBadge, ForeName) VALUES (#param1, #param2);";
cmd2.Parameters.Add(new SQLiteParameter("#param1", row.ForeBadge));
cmd2.Parameters.Add(new SQLiteParameter("#param2", row.ForeName));
cmd2.ExecuteNonQuery();
}
}
I'm getting this error:
That's because that's the only place you forgot to open the connection.
add this: SQLconn2.Open();
You forgot to open the connection.
SQLConn2.Open();
Related
I need to insert into a table "pass" or "fail", if from the query done there is a single fail instead of 'RProva' I have to put "fail" if the query can't find a single fail instead of 'RProva' I have to insert "pass", the query is working but I can't figure out how to do the if with the results of a query, maybe I have to use a "for"? Don't know. It is the attempt to make it, the second is the query where I have to insert the result of the possbile "IF"
1.
SqlCommand cmdRD = new SqlCommand("SELECT ResItem AS RD FROM tSE JOIN tL ON tSE.idSE=tL.idL WHERE tL.Selection=1");
var RD = cmdRD.ExecuteScalar();
var values = new List<string>();
using (cmdRD,sqliteCon)
{
using (SqlDataReader reader = cmdRD.ExecuteReader())
{
while (reader.Read())
{
values.Add(reader[0].ToString());
}
}
}
2.
SqlCommand cmd1 = new SqlCommand("INSERT INTO tSD(NomeItem,ResItemDet,DateStartDet,DateEndDet) OUTPUT inserted.Id VALUES (#NI,#RProva,#DATESE,#DATEED)");
cmd1.Parameters.AddWithValue("#DATESE", DATESE);
cmd1.Parameters.AddWithValue("#DATEED", DATEED);
cmd1.Parameters.AddWithValue("#NI", NI);
using (cmd1,sqliteCon)
{
foreach (var value in values)
{
if (value.Equals(pass))
{
cmd1.Parameters.AddWithValue("#RProva", value);
}
else
{
cmd1.Parameters.AddWithValue("#RProva", fail);
}
cmd1.ExecuteNonQuery();
}
}
int generatedId = Convert.ToInt32(cmd1.ExecuteScalar());
cmd1.Parameters.Clear();
SqlCommand cmd2 = new SqlCommand("UPDATE tSE SET FK_TSD_id = #tsdId FROM tL JOIN tSE ON tL.idL = tSE.idSE WHERE tL.Selection=1 ", sqliteCon);
cmd2.Parameters.AddWithValue("#tsdId", generatedId);
cmd2.ExecuteNonQuery();
MessageBox.Show("Dato Aggiunto");
}
sqliteCon.Close();
1.1
SqlCommand cmdRD = new SqlCommand("SELECT ResItem AS RD FROM tSE JOIN tL ON tSE.idSE=tL.idL WHERE tL.Selection=1", sqliteCon);
var RD = cmdRD.ExecuteScalar();
var tot =pass;
using (cmdRD)
{
using (SqlDataReader reader = cmdRD.ExecuteReader())
{
while (reader.Read())
{
if(reader[0].ToString()==fail)
{
tot = fail;
break;
}
}
MessageBox.Show(tot);
}
}
i'm arrived to that(1.1) it works but i've to insert the TOT into RProva
Based on your question and comment I think you misunderstood ExecuteScalar:
ExecuteScalar executes the query, and returns the first column of the first row in the result set returned by the query. learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.executescalar
I dont know the Type of "RD" or "PASS", but the IF in your example (when using ExecuteScalar) seems OK. Else when you are using ExecuteReader you should use some kind of an loop to iterate through the Items. Like this:
string pass = "abc"; // guessing types and values
string fail = "failed";
string sqliteCon = "Data Source=(localdb)\\MSSQLLocalDB;Database=BooksDb";
using (SqlConnection connection = new SqlConnection(sqliteCon))
{
connection.Open();
var queryString = #"SELECT ResItem AS RD
FROM tSE
JOIN tL ON tSE.idSE = tL.idL
WHERE tL.Selection=1";
var values = new List<string>();
using (SqlCommand command = new SqlCommand(queryString, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
values.Add(reader[0].ToString());
}
}
}
var queryInsert = #"INSERT INTO tSD (NomeItem,ResItemDet,DateStartDet,DateEndDet)
VALUES (#NI, #RProva, #DATESE, #DATEED)";
using (SqlCommand command2 = new SqlCommand(queryInsert, connection))
{
foreach(var value in values)
{
command2.Parameters.Clear();
if (value.Equals(pass))
{
command2.Parameters.AddWithValue("#RProva", value);
}
else
{
command2.Parameters.AddWithValue("#RProva", fail);
}
command2.ExecuteNonQuery();
}
}
}
Theres for sure a better way, but maybe this helps you out.
EDIT:
Here is how I would implement your code example:
using (SqlConnection sqliteCon = new SqlConnection(connection))
{
sqliteCon.Open();
var values = new List<string>();
var query = "SELECT ResItem AS RD FROM tSE JOIN tL ON tSE.idSE=tL.idL WHERE tL.Selection=1";
using (SqlCommand cmdRD = new SqlCommand(query, sqliteCon))
{
var RD = cmdRD.ExecuteScalar();
using (SqlDataReader reader = cmdRD.ExecuteReader())
{
while (reader.Read())
{
values.Add(reader[0].ToString());
}
}
}
int generatedId = 0;
var query2 = "INSERT INTO tSD(NomeItem,ResItemDet,DateStartDet,DateEndDet) OUTPUT inserted.Id VALUES (#NI,#RProva,#DATESE,#DATEED)";
using (SqlCommand cmd1 = new SqlCommand(query2, sqliteCon))
{
foreach (var value in values)
{
cmd1.Parameters.Clear();
cmd1.Parameters.AddWithValue("#DATESE", DATESE);
cmd1.Parameters.AddWithValue("#DATEED", DATEED);
cmd1.Parameters.AddWithValue("#NI", NI);
if (value.Equals(pass))
{
cmd1.Parameters.AddWithValue("#RProva", value);
}
else
{
cmd1.Parameters.AddWithValue("#RProva", fail);
}
cmd1.ExecuteNonQuery();
}
generatedId = Convert.ToInt32(cmd1.ExecuteScalar());
}
var query3 = "UPDATE tSE SET FK_TSD_id = #tsdId FROM tL JOIN tSE ON tL.idL = tSE.idSE WHERE tL.Selection=1 ";
using (SqlCommand cmd2 = new SqlCommand(query3, sqliteCon))
{
cmd2.Parameters.AddWithValue("#tsdId", generatedId);
cmd2.ExecuteNonQuery();
}
}
How to use Combobox.SelectedValue to construct WHERE clause?
conL.Open();
cmdL.Connection = conL;
cmdL.CommandText ="SELECT Id FROM dbAllServers WHERE Server_Names='" + cmb_SQLNames.SelectedValue +"'";
SQLiteDataReader r = cmdL.ExecuteReader();
while(r.Read())
{
serID = int.Parse(r[0].ToString());
MessageBox.Show("Current Selected Server ID is:..." + serID.ToString());
}
conL.Close();
An example of parameterized query, might be helpful:
string query = "SELECT Id FROM dbAllServers WHERE Server_Names=#server_name";
string serverName = cmb_SQLNames.SelectedValue;
using (SQLiteConnection connection = new SQLiteConnection(GetConnectionString()))
{
connection.Open();
using (var cmd = new SQLiteCommand(query, connection))
{
cmd.Parameters.Add(new SQLiteParameter("#server_name", serverName));
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// do your job here
}
}
}
}
I am having the below code where I am querying the MySQL database. I need to replace my select query to prepare statement
public static void ValidateName(List<Employees> EmpList, string Grp)
{
var connStr = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
string selectQuery;
for (int i = 0; i < EmpList.Count; i++)
{
selectQuery = "Select EmpName from Employee where group = #Grp AND #Name in (FirstName, LastName);";
using (MySqlConnection conn = new MySqlConnection(connStr))
using (MySqlCommand cmd = new MySqlCommand(selectQuery, conn))
{
cmd.Parameters.Add("#Grp", MySqlDbType.VarChar).Value = Grp;
cmd.Parameters.Add("#Name", MySqlDbType.VarChar).Value = EmpList[i].Name;
conn.Open();
var reader = cmd.ExecuteReader();
List<string> lineList = new List<string>();
while (reader.Read())
{
lineList.Add(reader.GetString(0));
}
if (lineList.Count <=0)
{
WriteValidationFailure(EmpList[i], "Name doesnot exists in the DB");
}
conn.Close();
}
}
}
This code works perfectly. But for improvement I need to use the prepare statements instead of the query I am using. Because I am having similar kinds of various validation in my code, I am not sure how to reuse the parameters effectively.
You are very close. Just call cmd.Prepare(), keep references to the parameters, and reuse the command:
public static void ValidateName(List<Employees> EmpList, string Grp)
{
var connStr = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
string selectQuery;
selectQuery = "Select EmpName from Employee where group = #Grp AND #Name in (FirstName, LastName);";
using (MySqlConnection conn = new MySqlConnection(connStr)) {
conn.Open();
using (MySqlCommand cmd = new MySqlCommand(selectQuery, conn))
{
var prmGrp = cmd.Parameters.Add("#Grp", MySqlDbType.VarChar);
var prmName = cmd.Parameters.Add("#Name", MySqlDbType.VarChar);
cmd.Prepare();
for (int i = 0; i < EmpList.Count; i++)
{
prmGrp.Value = Grp;
prmName.Value = EmpList[i].Name;
using (var reader = cmd.ExecuteReader()) {
List<string> lineList = new List<string>();
while (reader.Read())
{
lineList.Add(reader.GetString(0));
}
if (lineList.Count <=0)
{
WriteValidationFailure(EmpList[i], "Name doesnot exists in the DB");
}
}
}
}
conn.Close();
}
}
I'm trying to make a query into the Clients table, when the user enters a mobile number, the code checks if it matches any record, if it does, it returns the client's Name & Address into text boxes, but I'm getting this error "Object reference is not set to an instance of an object" by the time I enter anything into that textbox
here is the code, what could be the problem?
private void textBox11_TextChanged(object sender, EventArgs e)
{
clientsearch();
clientsearch2();
}
public void clientsearch()
{
using (System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data source=|DataDirectory|\\crepeDB.accdb;"))
{
conn.Open();
string query = #"select Cname From Clients where Cmobile = #mobile";
System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand(query, conn);
cmd.Parameters.Add("#mobile", System.Data.OleDb.OleDbType.Integer).Value = textBox11.Text;
cmd.ExecuteNonQuery();
string result = cmd.ExecuteScalar().ToString();
textBox12.Text = #result;
}
}
public void clientsearch2()
{
using (System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data source=|DataDirectory|\\crepeDB.accdb;"))
{
conn.Open();
string query = #"select Caddress From Clients where Cmobile = #mobile";
System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand(query, conn);
cmd.Parameters.Add("#mobile", System.Data.OleDb.OleDbType.Integer).Value = textBox11.Text;
cmd.ExecuteNonQuery();
string result = cmd.ExecuteScalar().ToString();
textBox13.Text = #result;
}
}
string result = cmd.ExecuteScalar().ToString();
textBox12.Text = #result;
#result isn't anything. You just want result. Additionally, sending separate queries to the server for this data is pointlessly inefficient. Do this instead:
public void clientsearch()
{
string query = #"select Cname, Caddress From Clients where Cmobile LIKE #mobile + '*'";
using (var conn = new System.Data.OleDb.OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data source=|DataDirectory|\\crepeDB.accdb;"))
using (var cmd = System.Data.OleDb.OleDbCommand(query, conn))
{
cmd.Parameters.Add("#mobile", System.Data.OleDb.OleDbType.Integer).Value = textBox11.Text;
conn.Open();
using (var rdr = cmd.ExecuteReader())
{
if (rdr.Read())
{
textBox12.Text = rdr["Cname"].ToString();
textBox13.Text = rdr["Caddress"].ToString();
}
rdr.Close();
}
}
}
Finally, it's better style to also abstract your database code away from user interface. Ideally you would return a Client class, but since I don't see one I'll show an example using a tuple instead:
public Tuple<string, string> FindClientByMobile(string mobile)
{
string query = #"SELECT Cname, Caddress FROM Clients WHERE Cmobile LIKE #mobile + '*'";
using (var conn = new System.Data.OleDb.OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data source=|DataDirectory|\\crepeDB.accdb;"))
using (var cmd = System.Data.OleDb.OleDbCommand(query, conn))
{
cmd.Parameters.Add("#mobile", System.Data.OleDb.OleDbType.Integer).Value = mobile;
conn.Open();
using (var rdr = cmd.ExecuteReader())
{
rdr.Read();
return Tuple<string, string>.Create(rdr["Cname"].ToString(), rdr["Caddress"].ToString());
}
}
}
If you're playing with a Visual Studio 2017 release candidate, you can also use the new Tuple shortcuts:
public (string, string) FindClientByMobile(string mobile)
{
string query = #"SELECT Cname, Caddress FROM Clients WHERE Cmobile LIKE #mobile + '*'";
using (var conn = new System.Data.OleDb.OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data source=|DataDirectory|\\crepeDB.accdb;"))
using (var cmd = System.Data.OleDb.OleDbCommand(query, conn))
{
cmd.Parameters.Add("#mobile", System.Data.OleDb.OleDbType.Integer).Value = mobile;
conn.Open();
using (var rdr = cmd.ExecuteReader())
{
rdr.Read();
return (rdr["Cname"].ToString(), rdr["Caddress"].ToString());
}
}
}
And then use them like this:
private void textBox11_TextChanged(object sender, EventArgs e)
{
var result = FindClientByMobile(textBox11.Text);
textBox12.Text = result.Item1;
textBox13.Text = result.Item2;
}
I need to get some mysql data into another mysql reader request anyway to workaround that I apparently can't have 2 readers open at the same time it will all end up in a datagrid
public void DBSelectPraktikanter(object sender)
{
string Command = "SELECT * FROM forlob WHERE firmaid = N'" + firmaid + "'";
MySqlConnection sqlConnection1 = new MySqlConnection(connectionString);
MySqlCommand command = new MySqlCommand(Command, sqlConnection1);
sqlConnection1.Open();
MySqlDataReader reader = command.ExecuteReader();
var items = new List<praktikanter>();
if (reader.HasRows)
{
while (reader.Read())
{
string praktikantid = String.Format("{0}", reader["praktikantid"]);
string Command2 = "SELECT * FROM praktikanter WHERE id = N'" + praktikantid + "'";
MySqlCommand command2 = new MySqlCommand(Command, sqlConnection1);
MySqlDataReader reader2 = command.ExecuteReader();
if (reader.HasRows)
{
while (reader2.Read())
{
Praktikant = String.Format("{0}", reader["Navn"]);
}
}
string Fra = String.Format("{0}", reader["fra"]);
string Til = String.Format("{0}", reader["til"]);
items.Add(new praktikanter(Praktikant, Fra, Til));
}
}
sqlConnection1.Close();
var grid = sender as DataGrid;
grid.ItemsSource = items;
}
Instead of nesting MySqlCommands and looping the first resultset to query again the database to collect all of your data you should really use one query. Also use the using-statement to ensure that the connection gets closed even on error and use sql-parameters to avoid sql-injection issues:
var items = new List<praktikanter>();
string sql = #"SELECT p.*, f. Navn
FROM praktikanter p INNER JOIN forlob f ON p.id = f.praktikantid
WHERE f.firmaid = #firmaid";
using (var con = new MySqlConnection(connectionString))
using (var command = new MySqlCommand(sql, con))
{
command.Parameters.Add(new MySqlParameter("#firmaid", MySqlDbType.VarChar).Value = firmaid);
con.Open();
using (var rd = command.ExecuteReader())
{
while (rd.Read())
{
string praktikant = rd.GetString("Navn");
string fra = rd.GetString("Fra");
string til = rd.GetString("Til");
items.Add(new praktikanter(praktikant, fra, til));
}
}
}