I am creating an application, where I can add a customer's first name, last name, email, the date, service type (pc repair), the technician PC brand, pc type, type of OS, and the problem with the computer. I am able to insert data into the MySQL database using phpMyAdmin.
However, I a stuck on this part. I am trying to view the service order that was just created. I would like to load the combobox by the last name of the customer, and once I click on the customer's name, it populates all the fields that were mentioned above and the service number that it was inserted into the database. I am having issues loading the combobox and texfields.
Any ideas are appreciated! If a combobox is a bad idea and there is a better way, please let me know! I tried this code, but SQLDataAdapter is not working for me. I somehow can't find an example that I can relate too.
private void cbViewServices_SelectedIndexChanged(object sender, EventArgs e)
{
if (cbViewServices.SelectedIndex >- 1)
{
string lastName = cbViewServices.SelectedValue.ToString();
MySqlConnection conn = new MySqlConnection("server=localhost;uid=******;password=**********;database=dboserviceinfo;");
conn.Open();
SqlDataAdapter da = new SqlDataAdapter("select distinct LastName from tserviceinfo where LastName='" + lastName + "'", conn);
DataSet ds = new DataSet();
da.Fill(ds); conn.Close();
}
}
I do not recommend using the 'Lastname' as a parameter to load your details since that field most likely isn't unique. Unless that is the case in your program.
This sample does the following:
Load customer ID (or lastname in your case) to a combobox.
Handle the combobox's change event and pass it as a parameter to a
method that will use that to load the details.
Load the customer details using the passed parameter.
A couple of guidelines:
Enclose disposable objects in a 'using' statement so it will be
disposed properly.
Do not use string concatenation to create your SQL statements. Use
SQL parameters instead, that way you'll avoid SQL injection and make
your code clearer.
Take a look at MySQL .NET connector provider documentation for best practices.
//Load customer ID to a combobox
private void LoadCustomersId()
{
var connectionString = "connection string goes here";
using (var connection = new MySqlConnection(connectionString))
{
connection.Open();
var query = "SELECT Id FROM Customers";
using (var command = new MySqlCommand(query, connection))
{
using (var reader = command.ExecuteReader())
{
//Iterate through the rows and add it to the combobox's items
while (reader.Read())
{
CustomerIdComboBox.Items.Add(reader.GetString("Id"));
}
}
}
}
}
//Load customer details using the ID
private void LoadCustomerDetailsById(int id)
{
var connectionString = "connection string goes here";
using (var connection = new MySqlConnection(connectionString))
{
connection.Open();
var query = "SELECT Id, Firstname, Lastname FROM Customer WHERE Id = #customerId";
using (var command = new MySqlCommand(query, connection))
{
//Always use SQL parameters to avoid SQL injection and it automatically escapes characters
command.Parameters.AddWithValue("#customerId", id);
using (var reader = command.ExecuteReader())
{
//No customer found by supplied ID
if (!reader.HasRows)
return;
CustomerIdTextBox.Text = reader.GetInt32("Id").ToString();
FirstnameTextBox.Text = reader.GetString("Firstname");
LastnameTextBox.Text = reader.GetString("Lastname");
}
}
}
}
//Pass the selected ID in the combobox to the customer details loader method
private void CustomerIdComboBox_SelectedIndexChanged(object s, EventArgs e)
{
var customerId = Convert.ToInt32(CustomerIdComboBox.Text);
LoadCustomerDetailsById(customerId);
}
I'm not entirely sure if this is what your looking for but most of the guidelines still applies.
Hope this helps!
Try something like this to bind data to the combo box:
public void ListCat()
{
DataTable linkcat = new DataTable("linkcat");
using (SqlConnection sqlConn = new SqlConnection(#"Connection stuff;"))
{
using (SqlDataAdapter da = new SqlDataAdapter("SELECT LastName FROM list WHERE LastName <> 'NULL'", sqlConn))
{
da.Fill(linkcat);
}
}
foreach (DataRow da in linkcat.Rows)
{
comboBox1.Items.Add(da[0].ToString());
}
}
Taken from my own question.
SqlDataAdapter is used to communicate with SQL Server rather than MySQL.
Try the following:
MySqlDataAdapter da = new MySqlDataAdapter("select distinct LastName from tserviceinfo where LastName='" + lastName + "'", conn);
We can also use while loop. When completing the database connection after the SQLDatareader we can use while loop.
"userRead " is SQLData reader
while (userRead.Read())
{
cboxReportNo.Items.Add(userRead[1].ToString());
}
bind your dataset in ComboBox DataSource
this.comboBox1.DataSource = ds;
this.comboBox1.DisplayMember = "LastName";
this.comboBox1.ValueMember = "Id";
this.comboBox1.SelectedIndex = -1;
this.comboBox1.AutoCompleteMode = AutoCompleteMode.Append;
this.comboBox1.AutoCompleteSource = AutoCompleteSource.ListItems;
//USING
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Data;
namespace YourNamespace
{
//Initialization
string connetionString = null;
SqlConnection cnn;
SqlCommand cmdDataBase;
SqlDataReader reader;
DataTable dt;
public frmName()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
FillComboNameOfCombo();
}
void FillcmbNameOfCombo()
{
string sqlQuery = "SELECT * FROM DATABASENAME.[dbo].[TABLENAME];";
connetionString = "Data Source=YourPathToServer;Initial Catalog=DATABASE_NAME;User ID=id;Password=pass";
cnn = new SqlConnection(connetionString);
cmdDataBase = new SqlCommand(sqlQuery, cnn);
try {
cnn.Open();
reader = cmdDataBase.ExecuteReader();
dt = new DataTable();
dt.Columns.Add("ID", typeof(string));
dt.Columns.Add("COLUMN_NAME", typeof(string));
dt.Load(reader);
cnn.Close();
cmbGender.DataSource = dt;
cmbGender.ValueMember = "ID";
cmbGender.DisplayMember = "COLUMN_NAME";
dt = null;
cnn = null;
cmdDataBase = null;
connetionString = null;
reader = null;
}
catch (Exception ex) {
MessageBox.Show("Can not open connection ! " + ex.ToString());
}
}
}
Related
I am trying to store sql data that I have for a voucher id and voucher amount into a variable and display it into a label on a click of a button.
protected void Button1_Click(object sender, EventArgs e)
{
string voucherId = String.Empty;
string voucherAmount = String.Empty;
string queryVoucherId = "select voucherid from ReturnForm where email = '" + Session["username"] + "';";
string queryVoucherAmount = "select voucheramount from ReturnForm where email = '" + Session["username"] + "';";
int index = 0;
using (SqlConnection con = new SqlConnection(str))
{
SqlCommand cmd = new SqlCommand(queryVoucherId, con);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
voucherId = reader[index].ToString();
index++;
}
}
using (SqlConnection con = new SqlConnection(str))
{
SqlCommand cmd = new SqlCommand(queryVoucherAmount, con);
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
voucherAmount = reader[index].ToString();
index++;
}
}
if (txtVoucher.Text == voucherId)
{
Label3.Visible = true;
Label3.Text = voucherAmount;
}
}
When I click the button its giving me an error saying that the index is out of bounds.
Building on #JSGarcia's answer - but using parameters as one ALWAYS should - you'd get this code:
string email = Session['username'];
string query = $"SELECT voucherid, voucheramount FROM ReturnFrom WHERE Email = #email";
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand(query, conn))
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
// set the parameter before opening connection
// this also defines the type and length of parameter - just a guess here, might need to change this
cmd.Parameters.Add("#email", SqlDbType.VarChar, 100).Value = email;
conn.Open();
sda.Fill(dt);
conn.Close();
}
Personally, I'd rather use a data class like
public class VoucherData
{
public int Id { get; set; }
public Decimal Amount { get; set; }
}
and then get back a List<VoucherData> from your SQL query (using e.g. Dapper):
string query = $"SELECT Id, Amount FROM ReturnFrom WHERE Email = #email";
List<VoucherData> vouchers = conn.Query<VoucherData>(query).ToList();
I'd try to avoid the rather clunky and not very easy to use DataTable construct...
I strongly recommend combining your sql queries into a single one, write it into a datatable and continue your logic from there. IMHO it is much cleaner code:
string email = Session['username'];
string query = $"SELECT voucherid, voucheramount FROM ReturnFrom where Email = '{email}'";
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = conn.CreateCommand())
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
conn.Open();
sda.Fill(dt);
conn.Close();
}
// Work with DataTable dt from here on
...
Well, one more big tip?
You ONLY as a general rule need a dataadaptor if you going to update the data table.
And you ONLY need a new connection object if you say not using the sql command object.
The sqlcommand object has:
a connection object - no need to create a separate one
a reader - no need to create a separate one.
Note how I did NOT create a seperate connection object, but used the one built into the command object.
And since the parameter is the SAME in both cases? Then why not re-use that too!!
So, we get this:
void TestFun2()
{
String str = "some conneciton???";
DataTable rstVouch = new DataTable();
using (SqlCommand cmdSQL =
new SqlCommand("select voucherid from ReturnForm where email = #email",
new SqlConnection(str)))
{
cmdSQL.Parameters.Add("#email", SqlDbType.NVarChar).Value = Session["username"];
cmdSQL.Connection.Open();
rstVouch.Load(cmdSQL.ExecuteReader());
// now get vouch amount
cmdSQL.CommandText = "select voucheramount from ReturnForm where email = #email";
DataTable rstVouchAmount = new DataTable();
rstVouchAmount.Load(cmdSQL.ExecuteReader());
if (rstVouch.Rows[0]["vourcherid"].ToString() == txtVoucher.Text)
{
Label3.Visible = true;
Label3.Text = rstVouchAmount.Rows[0]["voucheramount"].ToString();
}
}
}
Can anyone tell me why this isn't working? I don't get an error in the code, but the information (month, day) doesn't show up in the labels. The connection is active, the data is there. It just will not display.
The listbox (listNames) is populated from the database, and that works fine. What I want is for the MONTH and DAY information from the selected record from listbox to display as labels.
Thanks for any help.
private void listNames_SelectedIndexChanged(object sender, EventArgs e)
{
using (connection = new SqlConnection(connectionString))
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM members WHERE Name = " + listNames.SelectedItem.ToString(), connection))
{
DataTable showlistTable = new DataTable();
DataSet info = new DataSet();
adapter.Fill(showlistTable);
adapter.Fill(info);
labelDetailsMonth.Text = info.Tables[0].Rows[0]["Month"].ToString();
labelDetailsDay.Text = info.Tables[0].Rows[0]["Day"].ToString();
}
}
You need single quotes around string literals in SQL (your listNames.SelectedItem value). The best way to do this is by avoiding the string literal entirely and using a query parameter. This will also fix the gaping sql injection security hole:
private void listNames_SelectedIndexChanged(object sender, EventArgs e)
{
string sql = "SELECT * FROM members WHERE Name = #Name";
using (connection = new SqlConnection(connectionString))
using (SqlDataAdapter adapter = new SqlDataAdapter(sql, connection))
{
//guessing at column type/length here
adapter.SelectCommand.Parameters.Add("#Name", SqlDbType.NVarChar, 20).Value = listNames.SelectedItem;
DataSet info = new DataSet();
adapter.Fill(info);
labelDetailsMonth.Text = info.Tables[0].Rows[0]["Month"].ToString();
labelDetailsDay.Text = info.Tables[0].Rows[0]["Day"].ToString();
}
}
I need assistance to display sql server values in a windows forms. In the application below if the query returns a row then the values are displayed. I understand that I am to use sqldatareader but so far I have been unsuccessful how to add it.
SqlConnection ChuoDB_Connection = new SqlConnection("Data Source=test-PC\\tester;Initial Catalog=Chuo;Integrated Security=True;Pooling=False");
SqlDataAdapter select_adapt;
private void btn_guardian_student_search_Click(object sender, EventArgs e)
{
if (rd_btn_guardian_student_no.Checked == true)
{
DataSet ds = new DataSet();
SqlDataReader dr;
ChuoDB_Connection.Open();
select_adapt = new SqlDataAdapter("SELECT * FROM Guardian WHERE STUDENT_NO = #student_no", ChuoDB_Connection);
select_adapt.SelectCommand.Parameters.Add("#student_no", SqlDbType.Int).Value = Convert.ToInt32(txt_bx_guardian_student_search.Text);
select_adapt.Fill(ds);
if (ds.Tables[0].Rows.Count == 0)
{
lbl_guardian_student_search.Text = "No Guardian record exists for this student. Please enter the Guardian Information";
ChuoDB_Connection.Close();
}
if (ds.Tables[0].Rows.Count > 0)
{
lbl_guardian_student_search.Text = "";
while (dr.read())
{
txtBox1.Text = rdr.Item["DBFieldName1"].ToString();
txtBox2.Text = rdr.Item["DBFieldName2"].ToString();
}
}
}
}
I think you do not need DataAdapter and DataSet here.
Try just with the DataReader:
string _connectionString = "Data Source=test-PC\\tester;Initial Catalog=Chuo;Integrated Security=True;Pooling=False";
string _selectCommand = #"SELECT * FROM Guardian WHERE STUDENT_NO = #student_no";
here code for the click handler:
SqlParameter parameter = new SqlParameter("#student_no", SqlDbType.Int);
parameter.Value = Convert.ToInt32(txt_bx_guardian_student_search.Text);
using (IDbConnection connection = new SqlConnection(_connectionString))
{
connection.Open();
using (IDbCommand command = connection.CreateCommand())
{
command.Connection = connection;
command.CommandText = _selectCommand;
command.Parameters.Add("#student_no", SqlDbType.Int).Value = Convert.ToInt32(txt_bx_guardian_student_search.Text);
IDataReader reader = command.ExecuteReader();
if (reader.Read())
{
txtBox1.Text = reader["DBFieldName1"].ToString();
txtBox2.Text = reader["DBFieldName2"].ToString();
}
else
{
lbl_guardian_student_search.Text = "No Guardian record exists for this student. Please enter the Guardian Information";
}
}
}
To use a SqlDataReader you need to initialize it using the ExecuteReader method of a SqlCommand. So in your code you could discard all the part relative to the SqlDataAdapter
private void btn_guardian_student_search_Click(object sender, EventArgs e)
{
if (rd_btn_guardian_student_no.Checked == true)
{
using(SqlConnection cnn = new SqlConnection(......))
using(SqlCommand cmd = new SqlCommand(#"SELECT * FROM Guardian
WHERE STUDENT_NO = #student_no", cnn))
{
cnn.Open();
cnn.Add("#student_no", SqlDbType.Int).Value = Convert.ToInt32(txt_bx_guardian_student_search.Text);
using(SqlDataReader rd = new cmd.ExecuteReader())
{
if(!rd.HasRows)
lbl_guardian_student_search.Text = "No Guardian record exists for this student. Please enter the Guardian Information";
else
{
rdr.Read();
txtBox1.Text = rdr.Item["DBFieldName1"].ToString();
txtBox2.Text = rdr.Item["DBFieldName2"].ToString();
}
}
}
}
}
Note that I have moved the global connection object inside the code making it a local variable that is initialized inside a using block as well the command and the reader. They are disposable objects and should be disposed when you have finished with them. The Using Statement ensure correct dispose of these objects
Also note that keeping a connection opened all the time of your application is really a big NO-NO in database server applications. You hinder the server ability to serve more requests if you keep your connection constantly open. And there is no great penalty in restoring the server connection because ADO.NET has an infrastructure called Connection Pooling that allows you to restore your connection immediately
I am doing this for my own learning. It is not home work. All example I have found are for asp solutions.
I have a Grid and a DropDownList in a Winform.
The Grid has a DataSet a BindingSource and a TableAdapter.
I populate the dropdownlist with the tables in the DB as following:
public void FillDropDownList(string connString)
{
String Query = "SELECT * FROM information_schema.tables where Table_Name like 'Table%'";
using (var cn = new SqlConnection(connString))
{
cn.Open();
DataTable dt = new DataTable();
try
{
SqlCommand cmd = new SqlCommand(Query, cn);
SqlDataReader myReader = cmd.ExecuteReader();
dt.Load(myReader);
}
catch (SqlException e)
{
//to be completed
}
radDropDownList1.DataSource = dt;
radDropDownList1.ValueMember = "TABLE_NAME";
radDropDownList1.DisplayMember = "TABLE_NAME";
}
}
The line that loads the data in the grid is like this:
this.table_xxxTableAdapter.Fill(this.xxxDataSet.Table_xxx);
So I suspect that with these components I would need a new dataset for each table but I do not like to do that because new tables may be created in the future.
How can I change the table loaded in the grid selecting tables from the dropdownlist?
A DataSet requires that you specify the tables you may want to load at design time, but it sounds like you want to load these tables dynamically (because they may get added to the database from another source?)
If I'm understanding your question correctly, you should simply do this:
Whenever the user selects a table, load the selected table using a dynamic query and re-databind the grid to it. The code should look something like this. Note: This is untested code.
protected void radDropDownList_OnSelectedIndexChanged(object sender, EventArgs e)
{
DataTable dt = new DataTable();
string query = BuildQuery(radDropDownList.SelectedValue); //Pass in the table name
using (var cn = new SqlConnection(connString))
{
cn.Open();
try
{
SqlCommand cmd = new SqlCommand(query, cn);
using (var da = new SqlDataAdapter(cmd))
{
ad.Fill(dt);
}
}
catch (SqlException e)
{
//TODO: Handle this exception.
}
}
radGrid.DataSource = dt;
radGrid.DataBind();
}
private string BuildQuery(string table)
{
//TODO: Provide your own implementation for your query.
return string.Format(
#"SELECT * FROM {0}", table);
}
I have been trying to query a access database and displaying the results in a DataDrigView. The grid displays all the data when I use the "SELECT * FROM CustomerPayments". However once I try adding a Parameter to the query I get an error message by
adapter.Fill(ds); //No value given for one more required parameters
However I have already successfully use a query using a parameter in another part of my program, it only seems to happen when I want to display in a data grid
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Data.SqlClient; //Import database class
namespace WindowsFormsApplication1
{
public partial class frmCustomerDetails : Form
{
//Database
//Get connection from database
String connectionString = staticConnectionString.connectionString;
//Declare a connection object
OleDbConnection con;
//Declare a command object for the SQL
OleDbCommand cmd;
//Declare an accedd type reader to read SQL commands
OleDbDataReader dr;
String[] CustomerID = new String[500];
String[] CustomerName = new String[500];
String[] Street = new String[500];
String[] Area = new String[500];
String[] PostCode = new String[500];
String[] TelNo = new String[500];
String[] Email = new String[500];
int RecordNo = 0;
int LastRecord = 0;
public frmCustomerDetails()
{
InitializeComponent();
}
private void frmCustomerDetails_Load(object sender, EventArgs e)
{
try
{
//create a connection object to the database via string location
con = new OleDbConnection(connectionString);
//Open the connection to the database
con.Open();
//Creat a new command object
cmd = new OleDbCommand();
//Set the SQL command text
cmd.CommandText = "SELECT * FROM Customer WHERE CustomerID = #ID;";
cmd.Parameters.AddWithValue("#ID", GlobalVar.SelectedCustomer);
//Link the command to the connection so the correct DB is used
cmd.Connection = con;
//Run the command and store resulting table in the datareader
dr = cmd.ExecuteReader();
}
catch (Exception err)
{
//Any database errors jump here and output error message
MessageBox.Show("A database error has occurred: " + Environment.NewLine + err.Message);
}
finally
{
//Do this whatever happens
//This is so the first record will be displayed
//Connection and dr are left open until from closes so more records can be accessed
}
//dr.Read() gets the next in the results if possible
while (dr.Read())
{
//Fill the text boxes with data
CustomerID[RecordNo] = dr["CustomerID"].ToString();
CustomerName[RecordNo] = dr["Names"].ToString();
Street[RecordNo] = dr["Street"].ToString();
Area[RecordNo] = dr["Area"].ToString();
PostCode[RecordNo] = dr["PostCode"].ToString();
TelNo[RecordNo] = dr["TelNo"].ToString();
Email[RecordNo] = dr["Email"].ToString();
RecordNo = RecordNo + 1;
}
LastRecord = RecordNo;
RecordNo = 0;
ReadDisplay();
}
private void btnMenu_Click(object sender, EventArgs e)
{
var SelectCustomer = new frmSelectCustomer();
SelectCustomer.Show();
this.Close();
}
private void btnWeeklyOrders_Click(object sender, EventArgs e)
{
String connectionString = staticConnectionString.connectionString;
OleDbCommand command;
OleDbDataAdapter adapter;
con = new OleDbConnection(connectionString);
command = con.CreateCommand();
//create data set
DataSet ds = new DataSet();
//Clear the gride of data
CustomerInfo.DataSource = null;
//create a new dataset
ds = new DataSet();
//Open connection
con.Open();
//Run the query
command.CommandText = "SELECT * FROM CustomerPayments WHERE CustomerID = #ID;";
cmd.Parameters.AddWithValue("#ID", GlobalVar.SelectedCustomer);
adapter = new OleDbDataAdapter(command);
adapter.Fill(ds);
//close connection
con.Close();
//Populate grid with data
CustomerInfo.DataSource = ds.Tables[0];
}
private void ReadDisplay()
{
lblCustomerID.Text = CustomerID[RecordNo];
lblNames.Text = CustomerName[RecordNo];
lblStreet.Text = Street[RecordNo];
lblArea.Text = Area[RecordNo];
lblPostCode.Text = PostCode[RecordNo];
lblTelNo.Text = TelNo[RecordNo];
lblEmail.Text = Email[RecordNo];
}
}
}
You assigning parameter for incorrect OleDbCommand variable:
command.CommandText = "SELECT * FROM CustomerPayments WHERE CustomerID = #ID;";
cmd.Parameters.AddWithValue("#ID", GlobalVar.SelectedCustomer);
should be:
command.CommandText = "SELECT * FROM CustomerPayments WHERE CustomerID = #ID;";
command.Parameters.AddWithValue("#ID", GlobalVar.SelectedCustomer);