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;
}
Related
Could I use a read only collection here and drop the dataset? I am new to C# and I am stumped at how to do this. I have a dropdown-box that is being filled from a column in SQL that holds client names. I have a text-box that you enter an email address into that will update the email address in SQL with the values checked in the dropdown-box. Now when the email is entered into the textbox is there a way I can pull these saved values from SQL and have the checkboxes "auto" checked based on what is already in the table for the corresponding email? I have seen this done with coded values but not values from SQL. Also if an email has access to more than 1 client, the client names are pipe delimited when inserted into SQL.
Here Is what I have so far.
if (EmailList.Value == "") Connection ls = new Connection(); Recordset rs = new Recordset();
ls.Open(connections.myconn);
rs.Open("select email from users order by email", ls);
string emails = "";
while (!rs.EOF) { emails += rs.Fields[0].Value + " "; rs.MoveNext(); }
EmailList.Value = emails;
using (SqlCommand cmd1 = new SqlCommand("SELECT * FROM tracking_mpc order by ClientName"))
{
cmd1.CommandType = CommandType.Text;
cmd1.Connection = con1;
con1.Open();
webreport.DataSource = cmd1.ExecuteReader();
webreport.DataTextField = "ClientName";
webreport.DataValueField = "CltID";
webreport.DataBind();
con1.Close();
}
public string StringFromDatabase()
{
try
{
var dataSet = new DataSet();
string constr=ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
using (SqlConnection myConnect = new SqlConnection(constr))
myConnect.Open();
var command = new SqlCommand("SELECT Clients from users WHERE Email =" + EmailTextBox.Text)
{
CommandType = CommandType.StoredProcedure
};
var dataAdapter = new SqlDataAdapter { SelectCommand = command };
dataAdapter.Fill(dataSet);
return dataSet.Tables[0].Rows[0]["Clients"].ToString();
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
Here is a better implementation of your StringFromDatabase:
public List<string> GetClientNames(string email)
{
var constr=ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
var sql = "SELECT Clients FROM users WHERE Email=#email";
using (var conn = new SqlConnection(constr))
using (var cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("#email",SqlDbType.VarChar).Value = email;
conn.Open();
return ((string)cmd.ExecuteScalar()).Split('|').ToList();
}
}
Here is the same, but in a database agnostic way (works if you change your connection string to say MySql, Oracle, etc):
public List<string> GetClientNames(string email)
{
var constr = ConfigurationManager.ConnectionStrings["myConnectionString"];
var sql = "SELECT Clients FROM users WHERE Email=#email";
var factory = DbProviderFactories.GetFactory(constr.ProviderName);
using (var conn = factory.CreateConnection())
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
conn.ConnectionString = constr.ConnectionString;
var param = cmd.CreateParameter();
param.ParameterName = "#email";
param.Value = email;
cmd.Parameters.Add(param);
conn.Open();
return ((string)cmd.ExecuteScalar()).Split('|').ToList();
}
}
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 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();
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));
}
}
}