I have brought the data as below into the combobox. In my "BRANDS" table, the first column is brand_id and the second column is brand_name. I'm getting the names in the combobox, but I need to get the id's when saving it to the database. How can I do it ?
void markaekle() {
SqlCommand komut = new SqlCommand("Select * from MARKALAR", bgl.baglanti());
SqlDataReader dr = komut.ExecuteReader();
while (dr.Read())
{
comboBoxMarka.Properties.Items.Add(dr[1]);
}
bgl.baglanti().Close();
}
I need to save the id value to the database with a button like below:
private void BtnAnaGrupKaydet_Click(object sender, EventArgs e){
SqlCommand komut = new SqlCommand("INSERT INTO ANA_GRUP (marka_id,anagrup_isim,create_date) values (#p1,#p2,#p3)", bgl.baglanti());
komut.Parameters.AddWithValue("#p1", int.Parse(comboBoxMarka.Text));
komut.Parameters.AddWithValue("#p2", txtAnaGrup.Text);
komut.Parameters.AddWithValue("#p3", dateAnaGrup.DateTime);
komut.ExecuteNonQuery();
bgl.baglanti().Close();
MessageBox.Show("Ana Grup Sisteme Eklendi", "Bilgi", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
You can do many implementations.
Use Dataset and after executing your query, you can fill the dataset with the result. so you have all your data in your dataset. (define your database global) and after that when your button hits, you know which index of your combobox is selected. the index is the index of your dataset so you can access the id.
The simplest way is that use a Dictionary with Id and Name. after that is the same above.
To sum up, you need to have a global variable which stores the Id and Name of your query result. this variable can be a Dictionary or a dataset or ....
In order to get selected value instead of text. you would bind combobox like following:
List<DropDownKeyValue> list = new List<DropDownKeyValue>();
List.Add(new DropDownKeyValue
{
ID = 1,
Name = "Designation"
});
cmbSortBy.DisplayMember = "Name";
cmbSortBy.ValueMember = "ID";
cmbSortBy.DataSource = list;
to get selected ID you would use: cmbSortBy.SelectedValue object.
DropDownKeyValue class:
public class DropDownKeyValue
{
public int ID { get; set; }
public string Name { get; set; }
}
You need to bind your ComboBox to a DataSource. The easiest way for you to do this would be to amend your code along these lines:
SqlDataReader dr = komut.ExecuteReader();
var dt = new DataTable();
dt.Load(dr);
yourComboBox.DataSource = null;
yourComboBox.Items.Clear();
yourComboBox.DisplayMember = "brand_name";
yourComboBox.ValueMember = "brand_id";
yourComboBox.DataSource = dt;
You will now be able to access the id using yourComboBox.SelectedValue.
On the line below change values like.
komut.Parameters.AddWithValue("#p1",int.Parse(comboBoxMarka.SelectedValue.ToString()));
Related
I'm trying to learn how to use SQL in C#.
I ran into an issue and I can't figure it out. I made a ComboBox which reads data from my database and uses the database's Id as a ValueMember and displays a title.
I want to use the selected title's Id, so I can write the contents of a row to a RichTextBox with the click of a button.
So if I have selected the first title in the combobox, which has Id 1 in the database, I want to use that info to show the corresponding text in the richtextbox. I thought I figured it out, but it gives me an error:
String was not in correct format
The database is very simple:
Id
Title
Author
Story
1
aTitle
Me
Random Text
2
SomeTitle
NotMe
More Random Text
Here's my code:
private void LoadData()
{
using (Connection = new SqlConnection(ConnectionString)) //Make the connection
using (Adapter = new SqlDataAdapter("SELECT Title FROM StoryTable", ConnectionString))
{
Connection.Open();
DataTable TitleTable = new DataTable();
Adapter.Fill(TitleTable);
SelectionBox.ValueMember = "Id";
SelectionBox.DisplayMember = "Title";
SelectionBox.DataSource = TitleTable;
}
}
private void LoadButton_Click(object sender, EventArgs e)
{
int Id = Int32.Parse(SelectionBox.ValueMember); //String was not in correct format...
using (Connection = new SqlConnection(ConnectionString))
using (Adapter = new SqlDataAdapter("SELECT Story FROM StoryTable", ConnectionString))
{
Connection.Open();
var TextTable = new DataSet();
Adapter.Fill(TextTable);
StoryTextbox.Text = TextTable.Tables[0].Rows[Id]["Story"].ToString();
}
}
The immediate problem is that this:
int Id = Int32.Parse(SelectionBox.ValueMember);
should be this:
int Id = (int)SelectionBox.SelectedValue;
Actually, I just realised that there's another problem. You do this:
SelectionBox.ValueMember = "Id";
SelectionBox.DisplayMember = "Title";
yet this is your query:
SELECT Title FROM StoryTable
How are you going to bind the Id column when you're not even retrieving it?
SELECT Id, Title FROM StoryTable
I have a method which populates my ComboBox from a DataTable:
public string populateCompanyTransSellingEntityLookUp(ref System.Windows.Forms.ComboBox Combo, string Id, Contract Contract)
{
SqlCommand _comm = new SqlCommand();
_comm.Parameters.AddWithValue("#id", Id);
_comm.CommandText = "SELECT [name] FROM dbo.fnGetList(#id) ORDER BY [name]; ";
_comm.Connection = _conn;
_comm.CommandTimeout = _command_timeout;
DataTable dt = new DataTable();
try
{
SqlDataReader myReader = _comm.ExecuteReader();
dt.Load(myReader);
Combo.DataSource = dt;
Combo.DisplayMember = "name";
foreach (DataRow dr in dt.Rows)
{
if (dr["name"].ToString() == Contract.Company_Name.ToString())
{
Combo.Text = dr["company_int_name"].ToString();
}
}
}
catch
{
MessageBox.Show("Unable to populate Company Name LookUp");
}
return "";
}
I'm passing my saved value Contract.Company_Name into the forEach loop to find my required SelectedItem from the DataTable. The ComboBox is populated with my DataTable values from Combo.Datasource =dt; but my selected item isn't being set. The code compiles without exception. If I remove Datasource = dt;, theSelectedItemis set no problem. Why is theDatasourceoverriding mySelectedItem` and is there something I've missed with my binding?
Thanks all
At first you have to set the valueMember for sure. Then you can set the selectedValue Property instead of SelectedItem. The Item is one datasource record. So in your case it would be SelectedItem = dr! But iam not sure this is working.
Try this:
Combo.SelectedItem = dr;
I would suggest to use SelectedValue, then you don't need to loop through values "manually".
Also you don't need to use "heavy-weight" DataTable where you need just a collection of string values.
private IEnumerable<string> LoadNames(string id)
{
var query = "SELECT [name] FROM dbo.fnGetList(#id) ORDER BY [name]";
using (var connection = new SqlConnection("connectionString")
using (var command = new SqlCommand(query, connection)
{
// 36 is the size of the VarChar column in database(use your value)
command.Parameters.Add("#id", SqlDbType.VarChar, 36).Value = id;
connection.Open();
using (var reader = command.ExecuteReader())
{
var names = new List<string>();
while(reader.Read())
{
names.Add(reader.GetString(0));
}
return names;
}
}
}
public void Populate(ComboBox combobox, string id, Contract contract)
{
combobox.DataSource = LoadNames(id);
combobox.SelectedValue = contract.Copmpany_Name.ToString();
}
Few things to notice:
Dispose all objects which dealing with external resources (SqlConnection, SqlCommand and SqlDataReader)
Create SqlParameter with precise information about the type, for strings is important to provide size of the column in database. This information will improve SQL query performance on server side.
Don't pass combobox as a reference, populate method does not create new instance but only consume the given ComboBox instance.
Thank you for the help, I edited the code given that my problem was much more trivial.
public string populate_comboBox(ref System.Windows.Forms.ComboBox Combo)
{
SqlCommand _comm = new SqlCommand();
//edited for a simple one column sql query
_comm.CommandText ="SELECT [Column] FROM dbo.SQL_Table ORDER BY [Column];";
//MUST open sql connection to DB
SqlConnection conn = new SqlConnection(global_DB_String_Connection);
conn.Open();
_comm.Connection = conn;
DataTable dt = new DataTable();
try
{
SqlDataReader myReader = _comm.ExecuteReader();
dt.Load(myReader);
Combo.DataSource = dt;
Combo.DisplayMember = "ColumnName";
foreach (DataRow dr in dt.Rows)
{
//populates the combo box with query results
Combo.Text = dr["ColumnName"].ToString();
}
}
catch
{
Console.WriteLine("ComboBox Populate method has failed! ");
}
conn.Close();
return "";
}
I have in my database a table called students that have the number and name, address....
I have a form where I load all information for one student at a a time , and I have a next button and a back button.
How can I iterate to the next row (or previous row) in mysql (to be able to see the info of the next student) ?
I tried to use the primary key (auto increment) to iterate and when I want to see the next record I add 1 to the id or subtract 1 to see the previous record.
But if one record is deleted it will show an empty record.
Can you point me in the rigth direction?
I´m using WinForms
Sorry about my english..
string config = "server=localhost; userid = root; database = databaseName";
MySqlConnection con = new MySqlConnection(config);
MySqlDataReader reader = null;
string query = "SELECT * FROM students WHERE id = " + id; //id is the primary Key (auto increment)
MySqlCommand command = new MySqlCommand(query, con);
con.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
string studentName = (string)reader["studentName"];
string studentNum = (string)reader["studentNum"];
tbstudentName.Text = Convert.ToString(studentName);
tbstudentNum.Text = Convert.ToString(studentNum);
.....
}
con.Close();
You should not be calling the database each time you want to view the next record. Try reading all the data into a List.
I am not sure what you are using.. WinForms? WPF?
If WinForms you will need to do something like this.
public class Student
{//First create a class to hold your data in
public string Name { get; set; }
public string Num { get; set; }
}
public class MyForm : Form
{
int Index = 0;
List<Student> FormData { get; set; }
void GetData()
{
//This will hold all your data in memory so you do not have to make a database call each and every "iteration"
List<Student> dbData = new List<Student>();
string config = "server=localhost; userid = root; database = databaseName";
MySqlConnection con = new MySqlConnection(config);
MySqlDataReader reader = null;
string query = "SELECT * FROM students";
MySqlCommand command = new MySqlCommand(query, con);
con.Open();
reader = command.ExecuteReader();
while (reader.Read())
{
Student newStudent = new Student();
newStudent.Name = (string)reader["studentName"];
newStudent.Num = (string)reader["studentNum"];
//Add data to the list you created
dbData.Add(newStudent);
.....
}
con.Close();
//set the Form's list equal to the one you just populated
this.FormData = dbData;
}
private void BindData()
{
//If winforms
tbstudentName.Text = FormData[Index].Name;
tbstudentNum.Text = FormData[Index].Num;
//If wpf you will have to use view models and bind your data in your XAML but I am assuming you are using
//winforms here.
}
private void NextRecord()
{ //If you reached the end of the records then this will prevent IndexOutOfRange Exception
if (Index < FormData.Count - 1)
{
Index++;
BindData();
}
}
private void PreviousRecord()
{
if (Index != 0)
{
Index--;
BindData();
}
}
}
Now the above scenario will get it working quickly; however, there are better ways in doing this that would help you when you need to alter that data. I would recommend WinForms Binding. You can check it out here http://msdn.microsoft.com/en-us/library/c8aebh9k(v=vs.110).aspx
To get the next you can write:
select * from students where id > #id
order by id asc
limit 1
And to get previous
select * from students where id < #id
order by id desc
limit 1
DataReader Designed to quick one-time read.
If you want to hold the data, you need to fill memory arrays.
the DataTable implements it very well.
You will need to think a little different.
Getting id+1 you are being very careless.. Even identity, the Id can be another value and you will get an Exception.. I suppose that you don't want it.
You will need to Adjust your logic to return lines with top or, in mysql, limit statement..
This will be easy using lambda to use .Take() and Skip() methods...
You also can use the limit parameter to pass throug this sample.. you can understand..
MySQL skip first 10 results
Hope it helps.
I am sure that someone has asked this before, but I am not searching for the right terms or something because I just can't seem to find what I am looking for.
I have a class Packages:
class Packages
{
string PackageID {get; set;}
string PackageName { get; set; }
}
I have a list of packages in my context.
public class TransferJobContext
{
public string ImportFile;
public string WorkSheetName;
public DataSet TransferData;
public List<Packages> Packages = new List<Packages>();
}
I have a checkedListBox on my form that is bound to a datasource. Here is the section of code where I get the values into the checkedListBox
using (var connection = my_DB.GetConnection())
{
try
{
connection.Open();
SqlDataReader rdr = null;
dt = new DataTable();
string CommandText = "SELECT ID, Name FROM TABLENAME WHERE UPPER(Import_File_Source) LIKE '%abc%' and STATUS = 1";
SqlCommand cmd = new System.Data.SqlClient.SqlCommand(CommandText, connection);
rdr = cmd.ExecuteReader();
dt.Load(rdr);
cbPackages.DataSource = dt;
cbPackages.ValueMember = "ID";
cbPackages.DisplayMember = "Name";
}
catch (Exception E)
{
MessageBox.Show(E.Message.ToString());
}
connection.Close();
}
How do I add a new Package to the list when an item is checked using the value member and displaymember of the selected items?
Edit: Ok maybe I am going about this completely wrong. Instead of telling you what I have done, I'll tell you what I would like to happen.
I am presenting my user with a checkedlistbox that has a list of names with check boxes next to them. They can select more than one. This results in me having one or more ID(s) to use in my query and name(s) to use as a description. I need to pass around with my context the one or many id/name combinations of my "Package".
What is the best what to capture the ID/Name combination of the selections the user made and pass them into my context?
First: Fetch existing Packages from your database:
public function GetPackages() as List<Package>
{
using (var connection = my_DB.GetConnection())
{
try
{
connection.Open();
SqlDataReader rdr = null;
dt = new DataTable();
string CommandText = "SELECT ID, Name FROM TABLENAME WHERE UPPER(Import_File_Source) LIKE '%abc%' and STATUS = 1";
SqlCommand cmd = new System.Data.SqlClient.SqlCommand(CommandText, connection);
var packages = new List<Package>();
using(var reader = cmd.ExecuteReader())
{
do while(reader.Read())
{
packages.Add(new Package({ID = reader.GetString(0), Name = reader.GetString(1)})
}
}
cbPackages.DataSource = packages;
cbPackages.ValueMember = "ID";
cbPackages.DisplayMember = "Name";
return packages;
}
catch (Exception E)
{
MessageBox.Show(E.Message.ToString());
return new List<Package>();
}
connection.Close();
}
}
Second:
Assign the fetched packages to the instance of your context:
yourContext.Packages = GetPackages();
Third:
Fill the CheckedListBox with your packages:
cbPackages.DataSource = yourContext.Packages;
cbPackages.ValueMember = "ID";
cbPackages.DisplayMember = "Name";
Finally: After user input, get the checkedpackages and do whatever you want with them:
foreach (Package item in checkedListBox1.CheckedItems)
{
MessageBox.Show(Package.ID);
MessageBox.Show(Package.Name);
//do whatever you want here e.g. pass it back to the context
}
Sidenote: I would suggest you to rename Packages to Package, PackageID to ID and PackageName to Name (As already proposed in the example code).
Hopefully i don't sound confusing but i am not sure if what i am trying to get at is possible.
I have a select statement to get name, id, guid. I am setting the display to name and the value to Id for each combobox. Is there a way that i could also assign the guid to the combo box so that i could use it in my winforms app?
here is what i have for select statement:
private void secondChild_drp_SelectedIndexChanged(object sender, EventArgs e)
{
string secondChildId = secondChild_drp.SelectedValue.ToString();
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
using (SqlDataAdapter sda = new SqlDataAdapter("SELECT ... WHERE em.ChildID = (" + secondChildId + ")", conString))
{
DataTable dt = new DataTable();
sda.Fill(dt);
thirdChild_drp.ValueMember = "ID";
thirdChild_drp.DisplayMember = "DisplayName";
thirdChild_drp.DataSource = dt;
}
}
cmd.CommandText="StoreProcName";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ChildID", secondChildId);
cmd.Connection = con2;
con2.Open();
reader = cmd.ExecuteReader();
var guid = reader.ToString();
reader.Close();
con2.Close();
}
right now when i run this it tells me reader = cmd.ExecuteReader(); has Procedure or function StoreProcName has too many arguments specified.
i just want to get the guid associated with the id i passed in.
You can get the guid from your datatable as follows where yourselectedid is the combobox selecteditem id.
var results = from row in dt.AsEnumerable()
where row.Field<int>("ID") == yourselectedid
select row;
now from results you can get all the desired columns you want
Basically the same answer as I already posted here:
You could define a simple object which you are filling from your data base query:
public class Item
{
public int ID { get; set; }
public string DisplayName { get; set; }
public Guid Guid{ get; set; }
}
Your implementation could look something like this (some mockup data):
listBox1.DataSource = items;
listBox1.DisplayMember = "DisplayName";
listBox1.ValueMember = "ID";
Then based on the value you selected, you can query through your items and get the item:
var key = (int)listBox1.SelectedValue;
foreach (var existingItem in items)
{
if (existingItem.Key == key)
{
//woohoo got it!
Debug.Print(existingItem.Guid.ToString())
}
}
you can put both of the value in the value member, separated by whichever character for separator like : "12;0000-000-0000" then separate again the Value Menber with a String.Split.