refreshing comboBox after creating a new table in database - c#

In my code I created a table and exported a CSV file to it. in another section of my code the comboBox is populated with the table names from my database. This is shown below:
private void FillCombo()
{
try
{
string connectionString = "Data Source=LPMSW09000012JD\\SQLEXPRESS;Initial Catalog=Pharmacies;Integrated Security=True";
using (SqlConnection con2 = new SqlConnection(connectionString))
{
con2.Open();
string query = "SELECT * FROM INFORMATION_SCHEMA.TABLES ";
SqlCommand cmd2 = new SqlCommand(query, con2);
SqlDataReader dr2 = cmd2.ExecuteReader();
while (dr2.Read())
{
int col = dr2.GetOrdinal("TABLE_NAME");
comboBox1.Items.Add(dr2[col].ToString());
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
What am trying to achieve is to refresh the comboBox as to reflect the newly added table which was executed through the above function. What came to mind first was to create a button and rewrite the above function like this:
private void button1_Click_1(object sender, EventArgs e)
{
//this is where I would just rewrite the contents of the above function
}
As you guessed, it works but the values are duplicated. How do I refresh the comboBox without duplicating the existing info?

As I mentioned at comments you can clear items before recall method with,
combobox.Items.Clear();
Or you can add If statement at while loop like this,
while (dr2.Read())
{
int col = dr2.GetOrdinal("TABLE_NAME");
if (!comboBox1.Items.Contains(dr2[col].ToString()))
{
comboBox1.Items.Add(dr2[col].ToString());
}
}
So you don't need to clear items every recall.
Hope helps,

Related

How to get a list box to display its results based on previous combo box.

I am trying to populate a combo box from SQL where when I select an Item from the first box the options get limited in the 2nd box. The fist box has a selected index change event, but I can't seem to figure out how to limit the results.
Here is what I have:
private void cb_college_SelectedIndexChanged(object sender, EventArgs e)
{
lb_allMajors.Items.Clear();
lb_allMajors.Items.Add(cb_college.SelectedIndex);
}
private void populateMajors()
{
try
{
string SQL;
SQL = "SELECT DISTINCT major_name FROM majors";
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(SQL, conn);
conn.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
lb_allMajors.Items.Add(reader.GetString(0));
}
}
}
catch (SqlException err)
{
MessageBox.Show(err.Message);
}
}
Each major in the majors table in the database has a college ID column that links to the colleges table. So when you select a college (e.g. Business) I want the major box to only show majors in the college of business.
I'm not 100% on exactly what you're after or what the example is showing, but I think you just need to supply your populateMajors() method with a parameter containing the college ID, or the SelectedIndex, whichever you want to use.
For example:
private void cb_college_SelectedIndexChanged(object sender, EventArgs e)
{
populateMajors(cb_college.SelectedIndex); // OR More likely Get College ID from Combobox
}
private void populateMajors(int CollegeId)
{
try
{
string SQL;
SQL = "SELECT DISTINCT major_name FROM majors WHERE <yourcollegeindexcol> = " + CollegeId;
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(SQL, conn);
conn.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
lb_allMajors.Items.Add(reader.GetString(0));
}
}
}
catch (SqlException err)
{
MessageBox.Show(err.Message);
}
}
I doubt that SelectedIndex is the right parameter to send, but you get the picture.
You might find it better to use the ComboBox.DataSource property too rather than Items.Add - search for ComboBox.DataSource online to see it's usage.

Need to delete data from an access database in c#

I need to delete certain data from an access database when a button is clicked and it keeps throwing an error relating to the executeNonquery(), I'm really new to this I would appreciate any help, here is my code
private void btnDelete_Click(object sender, EventArgs e)
{
OleDbConnection myDb = new OleDbConnection(connectionString + DBFile);
myDb.Open();
if (ComboBoxSelection.SelectedIndex == 0)
{
OleDbCommand command = new OleDbCommand();
command.Connection = myDb;
foreach (DataGridViewRow myRow in dataGridView1.SelectedRows)
{
string query = "DELETE FROM Clients WHERE ClientID = '{int.Parse(txtEdit.text)}'";
command.CommandText = query;
}
command.ExecuteNonQuery();
myDb.Close();
}
else if (ComboBoxSelection.SelectedIndex == 1)
{
OleDbCommand command = new OleDbCommand();
command.Connection = myDb;
foreach (DataGridViewRow myRow in dataGridView1.SelectedRows)
{
string query = "DELETE FROM Clients WHERE ClientID = '{txtEdit.text}'";
command.CommandText = query;
}
command.ExecuteNonQuery();
myDb.Close();
}
}
Making a lot of assumptions about what you are trying to do, which is delete from the database every client id in the selected rows. This is a big assumption since you are using the same TextBox in your sample code for each row but I'm guessing this is a work in progress and you were going to get there eventually.
First, commands and connections are disposable resources so you should make sure they are Disposed when you are done with them. A common way to do that is to instantiate them in using blocks as I show below.
Second, you should always use parameterized queries, never concatenate strings together. I don't know if ClientID is a string or a number, you appear to use it both ways, but if someone typed ' OR 1=1; -- into the text box while the combobox was on index 1 then you could end up with everything deleted.
Lastly, you have a lot of duplication. Based on my assumptions, you can clean up your code to this:
private void btnDelete_Click(object sender, EventArgs e)
{
string query = "DELETE FROM Clients WHERE ClientID = #ClientID";
using (OleDbConnection myDb = new OleDbConnection(connectionString + DBFile))
using (OleDbCommand command = myDb.CreateCommand())
{
int clientid = 0;
command.CommandText = query;
OleDbParameter parClientID = new OleDbParameter("#ClientID", OleDbType.Integer);
command.Parameters.Add(parClientID);
myDb.Open();
foreach (DataGridViewRow myRow in dataGridView1.SelectedRows)
{
//Assume your client id is in a cell of the row? Zero for first, One for second, etc.
if (int.TryParse(myRow.Cells[0].ToString(), out clientid))
{
parClientID.Value = clientid;
command.ExecuteNonQuery();
}
}
}
}

Display a list of item to CheckListBox when comboBox item is selected

I have a windows form application. Inside the form, I have a ComboBox and a list box. When I select the comboBox, I want to display a list of item that the user can check in the checkListBox, I figured out how to bind data to comboBox part but I am not sure how to display a list of values so that the user can select in the checkListBox. Let say I have a list of items that stored in a SQL database call item_table, how can I display it to the checkListBox according to when I select from the comboBox? Code for reference will be appreciated. Thanks
For example,
let say the user select "Amy" from the comboBox, the checkListBox will display a list of item "item 1, item2, item3, item4".
when the user select "Brad" from the comboBox, it will display a list of item: "item2, item5, item10
etc
Here is my database table in (SQL) server
user_Detail
In my user_Detail table , I have 10 user and each of them have a primary key (userId) and a column (userName);
item_Detail
In my item_Detail table, I have 20 items and they also have a primary key (itemId) and a column (itemName)
In the sql console, I inner join the two table (which I am not sure if I need to do the same in my SqlCommand in the code )
Here is my sql command in the console.
select
user_Detail.userId,
user_Detail.userName,
item_Detail.itemId,
item_Detail.itemName
from
item_Detail
INNER JOIN user_Detail ON user_Detail.userId = item_Detail.itemId
Here is my code
namespace Test {
public partial class MainForm: Form {
SqlConnection myConn;
SqlCommand myCommand;
SqlDataReader myReader;
SqlDataAdapter myDa;
DataTable dt;
DataSet ds = new DataSet();
public MainForm() {
InitializeComponent();
// loadComboBox
loadComboBox();
}
//Connect to my db to fetch the data when the application load
private void loadComboBox() {
myConn = new SqlConnection("Server = localhost; Initial Catalog= dbName; Trusted_Connection = True");
string query = "Select * from user_Detail";
myCommand = new SqlCommand(query, myConn);
try {
myConn.Open();
myReader = myCommand.ExecuteReader();
string s = "<------------- Select an item ----------->";
itemComboBox.Items.Add(s);
itemComboBox.Text = s;
while (myReader.Read()) {
//declare a string
object userId = myReader[userId"];
object userName = myReader["userName"];
//my comboBox named userComboBox
userComboBox.Items.Add(userName.ToString());
}
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
//Display some items here (this is my checkListBox
private item_checkListBox(Object sender, EventArgs e){
}
private void load_item(){
}
I wish this could help you.
First, i just want to fix your loadComboBox() because reading it might lead to confusion.
private void loadComboBox() {
myConn = new SqlConnection("Server = localhost; Initial Catalog=dbName; Trusted_Connection = True");
string query = "Select * from user_Detail";
myCommand = new SqlCommand(query, myConn);
try {
myConn.Open();
myReader = myCommand.ExecuteReader();
string s = "<------------- Select an item ----------->";
itemComboBox.Items.Add(s);
itemComboBox.Text = s;
while (myReader.Read()) {
//declare a string
string userId = myReader["userId"].toString();
string userName = myReader["userName"].toString();
//my comboBox named userComboBox
userComboBox.Items.Add(userName);
}
myConn.Close();
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
Make sure to close sql connections after using it. Just open it again if youre going to use it.
Now, you added the userName of your users on your combobox.
Next lets create an event that will be fired whenever you choose from your combobox.
userComboBox.SelectedIndexChanged += (o,ev) => { ChangeCheckListItems(); };
The code above can be read as "if userComboBox changed selected index, call ChangeCheckListItems() method." Whenever you change selection, we will call the said method. You can put that code on your class constructor.
Now what does ChangeCheckListItems() method must contain.
private void ChangeCheckListItems(){
myCheckListBox.Items.Clear();
string selectedText = userComboBox.Text;
switch(selectedText){
case "Amy":
AddItemsForAmy();
break;
case "Brad":
AddItemsForBrad();
break:
}
}
So first, we make sure we clear the myCheckListBox before adding the items to avoid duplication since this method trigger every selection change.
Next we get the selected text from the userComboBox.
Then we will use a switch to choose what we will do depends on the selected userComboBox.
AddItemsForAmy() and AddItemsForBrad() are only example methods.
For example:
private void AddItemsForAmy(){
myConn = new SqlConnection("Server = localhost; Initial Catalog=dbName Trusted_Connection=true;"
string query = "Select * from item_Detail where itemId % 2 = 0"
myCommand = new SqlCommand(query, myConn);
try{
myConn.Open();
myReader = myCommand.ExecuteReader();
while(myReader.Read()){
string itemName = myReader["itemName"].toString();
myCheckListBox.Items.Add(itemName);
}
myConn.Close();
}
catch(SqlExcetion ex){
MessageBox.Show(ex.Message);
}
}
So in my example above, I selected all items with itemId that are even numbers.
And then on while() part, I added those items to the checklistbox.
Its your choice on what items are you going to display for Amy,Brad and other possible users on you database. You can also use parameterized method for shorter solution. Hope this helps. Sorry if its so long.

Not getting all results from SqlDataReader

Can anybody help me with the issue I'm seeing? For some reason when I run my page, I get my drop down lists to populate the data, however the first item in my database, per each SQL query, doesn't get populated.
For example, my database table is:
Category
1 Books
2 Clothing
3 Toys
4 Household Items
my first query -
SELECT Category FROM ProductCategories
my drop down list gets populated with
Clothing
Toys
Household Items
I have 2 other drop down lists I'm populating and those are doing the same thing. Once I get this figured out, I'll try to figure out the other problem I'm having with inserting the data in the database.
Thank you!
public partial class InsertItems : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection connection;
SqlCommand populateList;
SqlDataReader reader;
string connectionString = ConfigurationManager.ConnectionStrings["LakerBids"].ConnectionString;
connection = new SqlConnection(connectionString);
populateList = new SqlCommand("USE LakerBids SELECT Category FROM ProductCategories;" +
"USE LakerBids SELECT SubCategory FROM ProductSubCategories;" +
"USE LakerBids SELECT LName FROM Users", connection);
if (!IsPostBack)
{
try
{
connection.Open();
reader = populateList.ExecuteReader();
while (reader.Read())
{
pcategory.DataSource = reader;
pcategory.DataValueField = "Category";
pcategory.DataBind();
}
reader.NextResult();
while (reader.Read())
{
psubcategory.DataSource = reader;
psubcategory.DataValueField = "SubCategory";
psubcategory.DataBind();
}
reader.NextResult();
while (reader.Read())
{
user.DataSource = reader;
user.DataValueField = "LName";
user.DataBind();
}
reader.Close();
}
finally
{
connection.Close();
}
}
}
protected void AddItem(object sender, EventArgs e)
{
if (Page.IsValid)
{
SqlConnection connection;
SqlCommand insertData;
string connectionString = ConfigurationManager.ConnectionStrings["LakerBids"].ConnectionString;
connection = new SqlConnection(connectionString);
insertData = new SqlCommand("INSERT INTO Products (ProductName, ProductDesc, CategoryID, SubCatID, StatusID, UserID, ReservePrice, AuctionLength, BidID)" +
"VALUES (#ProductName, #ProductDesc, #CategoryID, #SubCatID, 1, #UserID, #ReservePrice, #AuctionLength, NULL)", connection);
insertData.Parameters.Add("#ProductName", System.Data.SqlDbType.NVarChar, 50);
insertData.Parameters["#ProductName"].Value = pname.Text;
insertData.Parameters.Add("#ProductDesc", System.Data.SqlDbType.NVarChar, 200);
insertData.Parameters["#ProductDesc"].Value = pdesc.Text;
insertData.Parameters.Add("#CategoryID", System.Data.SqlDbType.Int);
insertData.Parameters["#CategoryID"].Value = pcategory.SelectedIndex;
insertData.Parameters.Add("#SubCatID", System.Data.SqlDbType.Int);
insertData.Parameters["#SubCatID"].Value = psubcategory.SelectedIndex;
insertData.Parameters.Add("#UserID", System.Data.SqlDbType.Int);
insertData.Parameters["#UserID"].Value = user.SelectedIndex + 2;
insertData.Parameters.Add("#ReservePrice", System.Data.SqlDbType.Money);
insertData.Parameters["#ReservePrice"].Value = Convert.ToDecimal(reserveprice.Text);
insertData.Parameters.Add("#AuctionLength", System.Data.SqlDbType.Int);
insertData.Parameters["#AuctionLength"].Value = Convert.ToInt32(auctionlength.Text);
try
{
connection.Open();
insertData.ExecuteNonQuery();
Response.Redirect("Categories.aspx");
}
catch (Exception error)
{
dberror.Text = error.ToString();
}
finally
{
connection.Close();
}
}
}
}
You need to either use a DataSet or populate business entities within a collection and then bind to the collection.
List<Category> cats = new List<Category>();
while (reader.Read())
{
Category cat = new Category();
// fill properties from DataReader
cats.Add(cat);
}
pcategory.DataSource = cats;
pcategory.DataValueField = "Category";
pcategory.DataBind();
Sab0tr0n, I suspect one of two things are happening.
1) If you are saying the first item does not appear AFTER you do some kind of "Add Category" action, then it might be that the dropdown is populated BEFORE the insert completes. Meaning, you need to requery after allowing the insert to be committed to the database.
OR
2) Put a breakpoint on this line:
string connectionString = ConfigurationManager.ConnectionStrings["LakerBids"].ConnectionString;
Then confirm the connectionString is to the correct database. I've seen old config files that point to test or staging databases cause this kind of confusion.
Good luck. If these aren't the answer, maybe simplify your example to us or elaborate on exactly what you do with your application and when you see the problem.
The "reader.read()" statement in each block is actually reading the first row of data, so when you set the DataSource, the first row has already been read. Try taking it out
You should use "while (reader.Read())" if you want to iterate over each result, not bind the resulset in one step.
That being said, the comments about using a Dataset, seperating logic, etc., are valid

How to use SqlCommand and DataAdapter in order to manipulate SQL Server with C#

I create table called Department with 2 columns Department ID which is auto increment and Department Name
I create Navigate_Department() in order to walk through the department rows
System.Data.SqlClient.SqlConnection con;
DataSet Dep_ds;
System.Data.SqlClient.SqlDataAdapter Dep_da;
int Dep_MaxRows = 0;
int Dep_inc = 0;
private void ILS_Load(object sender, EventArgs e)
{
con = new System.Data.SqlClient.SqlConnection();
con.ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\ILS_DB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
con.Open();
Dep_ds = new DataSet();
string sql2 = "select * from Department order by DepartmentID";
Dep_da = new System.Data.SqlClient.SqlDataAdapter(sql2, con);
Dep_da.Fill(Dep_ds, "Department");
Navigate_Department();
Dep_MaxRows = Dep_ds.Tables["Department"].Rows.Count;
}
private void Navigate_Department()
{
DataRow dRow = Dep_ds.Tables["Department"].Rows[Dep_inc];
Dep_ID.Text =dRow.ItemArray.GetValue(0).ToString();
Dep_Name.Text = dRow.ItemArray.GetValue(1).ToString();
}
private void Move_Next_Click(object sender, EventArgs e)
{
if (Dep_inc != Dep_MaxRows-1)
{
Dep_inc++;
Navigate_Department();
}
else
{
MessageBox.Show("No More Records");
}
}
private void Move_back_Click(object sender, EventArgs e)
{
if (Dep_inc > 0)
{
Dep_inc--;
Navigate_Department();
}
else
{
MessageBox.Show("First Record");
}
}
private void Dep_Clear_Click(object sender, EventArgs e)
{
Dep_ID.Clear();
Dep_Name.Clear();
}
private void Dep_Add_Click(object sender, EventArgs e)
{
try
{
SqlCommand insCmd = new SqlCommand("insert into dbo.Department (DepartmentName) values ('" + Dep_Name.Text + "')", con);
Dep_da.InsertCommand = insCmd;
Dep_MaxRows = Dep_MaxRows + 1;
Dep_inc = Dep_MaxRows - 1;
Dep_Max.Text = Dep_MaxRows.ToString();
Dep_Current.Text = (Dep_MaxRows).ToString();
}
catch (Exception exceptionObject)
{
MessageBox.Show(exceptionObject.Message);
}
The problem is:
After I click clear button, I insert the department name into Dep_Name textbox then click add button. The name that I inserted didn’t get saved in the database, and if I click move back then move next in order to see what I inserted, I get a Index out of range exception in the Navigate_Department() method.
So did I make any mistake?
The reason the name you're inserting isn't saved in the database is because you never execute the insert command. Add:
int ret = Dep_da.Update(Dep_ds);
after the
Dep_da.InsertCommand = insCmd;
The variable ret will contain the number of rows successfully updated (inserted) - which in your case should be 1.
To add to what #N. Warfield wrote, if you simply append raw data into your SQL string that a user (or another system, for that matter) provides, you leave yourself wide-open to SQL injection attacks.
Rather than create the insert statement like this you should use the data adapter with an insert command, add a new DataRow instance to the table then use the data adapter to execute the update.
Alternatively you could execute the insert command within Dep_Add_Click by replacing the call to "Dep_da.InsertCommand = insCmd" with "insCmd.ExecuteNonQuery", however this would mean that you would need to re-run the select statement and repopulate the dataset from the database to get the data from the database into the dataset.

Categories

Resources