i'm trying to use my Textbox value from another form to a class to insert items to my database.
I tried creating another instance of my Form1 which is the name of the form I want to get the value from but it returns 0 items to my database when I click my submit button is there anyway to do this?
public void Insert()
{
Form1 mform = new Form1();
string query = "INSERT INTO parts (item_id, description, brand, model, color, quantity) VALUES('0', '"
+ mform.Description.Text
+ "','" + mform.Brand.Text
+ "','" + mform.Model.Text
+ "','" + mform.Color.Text
+ "','" + mform.Quantity.Text + "')";
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
cmd.ExecuteNonQuery();
this.CloseConnection();
}
}
When you instantiate a new instance of the Form1() object, you are assuming that the new instance's "Description, Brand, Model, Color and Quantity" TextBox's contains text? The default value of a TextBox.Text is the default value of its string property type, null.
Ideally, you will take the values that the user has populated from the form instance and then pass them into the DB like so:
public void Insert()
{
using (var mform = new Form1())
{
// Ensure that the user entered values...
if (mform.ShowDialog() == DialogResult.Ok)
{
string query = "INSERT INTO parts (item_id, description, brand, model, color, quantity) VALUES('0', '"
+ mform.Description.Text
+ "','" + mform.Brand.Text
+ "','" + mform.Model.Text
+ "','" + mform.Color.Text
+ "','" + mform.Quantity.Text + "')";
if (this.OpenConnection() == true)
{
var cmd = new MySqlCommand(query, connection);
cmd.ExecuteNonQuery();
this.CloseConnection();
}
}
}
}
Additionally, you should avoid inline SQL and instead use stored procedures, or at the very least use SqlParameter's.
No, you cannot access Form1 values in a class by creating new instance. To access textbox values you need to do the following:
Create public property in a class
Assign property with textbox value in some appropriate event (such as TextChanged)
Access property inside class to get textbox value and save it to database.
Example
Class:
public class DataAccess
{
public string IncomingValue { get; set; }
public string SaveToDatabase()
{
string valueToSave = IncomingValue;
// Insert into database
return "Success";
}
}
Form:
DataAccess access = new DataAccess();
private void textBox1_TextChanged(object sender, EventArgs e)
{
access.IncomingValue = textBox1.Text;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(access.SaveToDatabase());
}
Also, I would suggest you to use Parametrized Query. This will give you more readability and saves you from SQL injection and confusion.
Related
My issue can seem so trivial, but unfortunately I don't know how to solve that problem.
There's one table in one database. I have to add the data with clicking on the button to that table. When user clicks on the button, he's getting to some form where he/she can input the data. At the first time it would be good if I am able to input: id, kind of service, price. I've decided to create a new class where I would content all variables including these three variables. These variable are public.
Also I've decided to read the text from the textBoxes and to write this information to the variables of that class. In the second form there are 2 buttons. "Ok" and "Cancel". And I have decided to use ShowDialog.
I'm capable to output the table from the database to the DataGridView, but I am not well-aware how to add the data to my table and showcase that successfully in the datagridview after the inserting.
My class:
public class AllDataDB
{
public int id_serv;
public double price;
public string name;
}
The second form:
public partial class TypeService : Form
{
public AllDataDB Class;
public TypeService(AllDataDB t)
{
Class = t;
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
private void button1_Click(object sender, EventArgs e)
{
AllDataDB Class = new AllDataDB();
Class.id_serv = Convert.ToInt32(textBox3.Text);
Class.name = NameService.Text;
Class.price = Convert.ToDouble(PriceService.Text);
this.DialogResult = DialogResult.OK;
this.Close();
}
}
The work of the button calling the form and the query:
private void NewServe_Click(object sender, EventArgs e)
{
AllDataDB Class = new AllDataDB();
TypeService form = new TypeService(Class);
if (form.ShowDialog() == DialogResult.OK)
{ // відповідно до класу створюється новий запис. INSERT.
SqlConnection Con = new SqlConnection(connectionString);
Con.Open();
string Que = "INSERT INTO type_service " +
"VALUES(" + Class.id_serv + " ,'" + Class.name +
"' ," + Class.price + " );" +
"SELECT * FROM type_service";
SqlCommand cmd = new SqlCommand(Que, Con);
cmd.ExecuteNonQuery();
Con.Close();
SqlDataAdapter sqlDa = new SqlDataAdapter("SELECT * FROM type_service", Con);
DataTable d = new DataTable();
sqlDa.Fill(d);
dataGridView3.AutoGenerateColumns = false;
dataGridView3.DataSource = d;
}
}
There are many problems in the code shown. The most important ones are the way in which you read the values and how do you try to insert in the data. Inside the form TypeService you create a new instance of the AllDataDB class where you store the results. This instance is no more the one you have passed in input, so you need to read the values from the instance created by the TypeService form (stored in the global field Class). The second problem is the string concatenation of your values. This is a well known problem leading to parsing problems and sql injection. It is fixed by a parameterized query as shown below
private void NewServe_Click(object sender, EventArgs e)
{
// Do no pass an instance of Class here, just pass null
// or remove it at all if you don't plan to reuse the form for updating
TypeService form = new TypeService(null);
if (form.ShowDialog() == DialogResult.OK)
{
// Add the using statement to ensure a proper release of resources.
using SqlConnection Con = new SqlConnection(connectionString);
Con.Open();
// Parameterized query
string Que = "INSERT INTO type_service VALUES(#id,#name,#price);";
SqlCommand cmd = new SqlCommand(Que, Con);
cmd.Parameters.Add("#id", SqlDbType.Int).Value = form.Class.id_serv;
cmd.Parameters.Add("#name", SqlDbType.NVarChar).Value = form.Class.name;
cmd.Parameters.Add("#price", SqlDbType.Decimal).Value = form.Class.price;
cmd.ExecuteNonQuery();
SqlDataAdapter sqlDa = new SqlDataAdapter("SELECT * FROM type_service", Con);
DataTable d = new DataTable();
sqlDa.Fill(d);
dataGridView3.AutoGenerateColumns = false;
dataGridView3.DataSource = d;
}
}
There are other minor problems. In the TypeService form and in the class AllDataDB you have used global fields instead of the more flexible way of using properties.
public class AllDataDB
{
public int id_serv {get;set;}
public double price {get;set;}
public string name {get;set;}
}
as well
public AllDataDB Class {get;set;}
also, given the null passed to the constructor of the TypeService form you now need to ensure to not use that Class properties without cheching for its null value
Well, this aid was very useful. Thanks. But I've resolved this problem with creating a new 3 variables in the class TypeService. These variables are public too. And that is looking like this:
In the class TypeService:
public int i;
public string n;
public double p;
In the class MainCore:
cmd.Parameters.Add("#id", SqlDbType.Int).Value = form.i;// form.Class.id_serv;
cmd.Parameters.Add("#name", SqlDbType.NVarChar).Value = form.n;//form.Class.name;
cmd.Parameters.Add("#price", SqlDbType.Decimal).Value = form.p; //form.Class.price;
So it works. And I can remove the class AllDataDB, because that is not important and useful now.
Thanks for help.
I am new to C# and i am trying to insert some values to my database i created inside visual studio.
-I am creating a recipe application-
So in the form i have some components such as text boxes(For title,ingredients,description), a dropdown item(combobox) to specify if it's food or sweet and a button to insert all these data into my database.
When i am pressing the button i can add everything(all the text boxes) to the database except the dropdown value.
Here is the code inside the button_click
private void addItemButton_Click(object sender, EventArgs e)
{
string dat = "Insert into [Table](Title,Category,Ingredients,Description) Values('" + titleTextBox.Text + "','" + dropdownCategory.SelectedValue + "','" + addIngredientTextBox.Text + "','" + addDescriptionTextBox.Text + "')";
SqlConnection sqlCon = new SqlConnection(connectionString);
SqlCommand sqlCmd = new SqlCommand(dat, sqlCon);
sqlCon.Open();
sqlCmd.ExecuteNonQuery();
sqlCon.Close();
}
I make a code example, which can insert the combobox value to the database successfully.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string dat = string.Format("Insert into [Sample](Title,Category,Ingredients,Description)values('{0}','{1}','{2}','{3}')", textBox1.Text, comboBox1.SelectedItem,textBox2.Text,textBox3.Text);
string connectionString = #"connectionstring";
SqlConnection sqlCon = new SqlConnection(connectionString);
SqlCommand sqlCmd = new SqlCommand(dat, sqlCon);
sqlCon.Open();
sqlCmd.ExecuteNonQuery();
sqlCon.Close();
MessageBox.Show("success");
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.Items.AddRange(new object[] { "basketball","football", "volleyball" });
}
}
I would try to look into content of string dat.
It might contain invalid data if "dropdownCategory.SelectedValue" returns something
that you don't expect.
Other than that, order of Open(), ExecuteNonQuery() and Close() methods might be incorrect. Try to read docs of these methods.
Another thing that you should look into is error message that is returned(if there is one). They are usually pretty informative.
Ok i don't know if it's correct or not but it worked on me.
I changed
dropdownCategory.SelectedValue
to
dropdownCategory.Text
and it worked.
I asked this same question on SO-pt but no one seemed to understand the question, though I made it clear.
I have a form that I'll use to
Register customers in the database.
Alter any of the registers.
Show the registers.
Here I'm instantiating this form:
private void mnuRegister_Click(object sender, EventArgs e)
{
var frmRegister = new frmRegisterScreen();
frmRegister.Show();
}
As you can see, I'm calling the form from within a ToolStripMenuItem called mnuRegister.
Now, there are a number of properties from this form that I'm customizing at the Load` event, that'll make it more specific for registering the customers.
Below is the code:
private void frmRegisterScreen_Load(object sender, EventArgs e)
{
//set the database connection and the Sql command to be used
string conString = "Server = .\\sqlexpress; trusted_connection = yes; database=he_dados;";
SqlConnection con = new SqlConnection(conString);
string sel = "SET DATEFORMAT dmy;\n" //set date format to dd//mm/yyyy
+ "Insert into Customer(" +
"Name,IDCard,Phone,Address,Observation)" +
"values(" +
"'" + txtName.Text +
"','" + mskIDCard.Text +
"','" + mskPhone.Text +
"','" + txtAddress.Text +
"','" + txtObs.Text + "');";
SqlCommand selCmd = new SqlCommand(sel, con);
//set the form properties relate to the customer registration
lblMain.Text = "Register Customer";
tsbSave.Text = "Save Changes";
}
As you can see, this code is obviously intended to insert data in a table.
Now, what I want to do is to call another instance of this form:
private void mnuViewRegister_Click(object sender, EventArgs e)
{
var frmViewRegister = new frmRegisterScreen();
frmViewRegister.Show();
}
Then I want to set specific properties, required for me to make a simple query using the same form, for example:
private void frmRegisterScreen_Load(object sender, EventArgs e)
{
//set the database connection and the Sql command to be used
string conString = "Server = .\\sqlexpress; trusted_connection = yes; database=he_dados;";
SqlConnection con = new SqlConnection(conString);
string sel = "Select * from Customer;";
SqlCommand selCmd = new SqlCommand(sel, con);
//set the form properties relate to the customer registration
lblMain.Text = "View Customer Registers";
tsbSave.Text = "View";
}
In other words, I would like to have event calls specific to the instance of the form, instead of having one event that's valid for any of the instances.
Is that possible?
If you find yourself configurating a great deal of UI elements, then just create separate Forms. It's not like they cost you anything, and they'll be easier to maintain. But it looks like you're only changing a couple of UI elements (like the label), so that's not too bad.
Either move the configuration logic into two separate methods on the Form, like ConfigureForRegistration and ConfigureForViewingRegistration, and then call the appropriate one when you instantiate the Form:
var frmRegister = new frmRegisterScreen();
frmRegister.ConfigureForRegistration();
frmRegister.Show();
Or you could create an enumeration for each possible view, and pass a value in when you instantiate the Form:
public enum ScreenOption
{
Register,
AlterRegister,
ViewRegister
}
public class frmRegisterScreen
{
public frmRegisterScreen(ScreenOption option)
{
switch (option)
{
case ScreenOption.ViewRegister:
//set the database connection and the Sql command to be used
string conString = "Server = .\\sqlexpress; trusted_connection = yes; database=he_dados;";
SqlConnection con = new SqlConnection(conString);
break;
...
}
}
}
var frmRegister = new frmRegisterScreen(ScreenOption.ViewRegister);
frmRegister.Show();
So I have a class and a form.
The class hosts the MySQL code and the form holds the events that trigger the code in the MySQL class
// Code that acceses the class
// This triggers a method that is supposed to get the next record from the database.
private void next_Click(object sender, RoutedEventArgs e)
{
// Tag.text is the auto incremented unique record number.
// The MySQL code is meant to get the next record ahead of the number in tag.text
// in the corresponding table field.
usersMysql.RegForm_Next(tag.Text);
}
this next part is the method that accesses the MySQL code meant to fetch the next record
public void RegForm_Next(string tag_Value)
{
// tagValue now holds the number, which was in tag.text in the previous page, as a string
// tagValue has already been predeclared as a string
tagValue = tag_Value;
// Navigation is the method that holds the MySQL code.
// By passing "Forward", the method has a code to tell from that, which query to excecute.
Navigation("Forward");
}
The next code is the MySQL code meant to fetch the record
// Command to go to the next or previous rexord
public void Navigation(string scroll)
{
if (scroll == "Forward")
{
query = "select * from temp.signup where tag = (select min(tag) from temp.signup where tag > '" + tagValue + "' );";
}
if (scroll == "Backward")
{
query = "select * from temp.signup where tag = (select max(tag) from temp.signup where tag < '" + tagValue + "' );";
}
//Database connection parameters
string sqlcon = "datasource = " + datasource + ";" + "port=" + port + ";" + "username=" + username + ";" + "password=" + password + ";";
MySqlConnection con = new MySqlConnection(sqlcon);
MySqlDataReader rdr;
MySqlCommand cmd = new MySqlCommand(query, con);
//Excecution
try
{
//If the connection is Open
con.Open();
{
rdr = cmd.ExecuteReader();
while (rdr.Read())
{
// Declarations
// All these strings have been declared under the public class declaration.
sid = GetString(rdr, "id");
stag = GetColumnValueAsString(rdr, "tag");
sfirst = GetString(rdr, "first");
sfourth = GetString(rdr, "surname");
sdob = rdr.GetString("dob");
ssex = rdr.GetString("sex");
susername = GetString(rdr, "username");
spassword = GetString(rdr, "password");
}
con.Close();
}
}
catch (Exception ex)
{
ModernDialog.ShowMessage(ex.Message, "SQL related error: Nav", MessageBoxButton.OK);
}
}
Now this where the problem comes in. I need to bind the strings values to textboxes back in the previous page that called the method in the MySQL class up.
// This is how the ID binding was set up for example.
// This is where sid was declared.
string sid;
public string ID
{
get
{
return sid;
}
set
{
sid = value;
RaisePropertyChanged("ID");
}
}
And this is how the textbox binding was set up
<TextBox x:Name="id" Text="{Binding ID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged }" Margin="158,46,453,468" FontSize="13" TabIndex="1" />
I've set the data context in the page wit the textboxes but the strings are never loaded back into the textbox
public registrationForm()
{
InitializeComponent();
usersMysql = new users.MySQL.usersMySQL();
DataContext = usersMysql;
}
I can confirm that the strings are being loaded. I've tested with a message box. But nothing shows up in the text boxes.
This is the function I use for "propertyChanged" in the class
//Property changed
private void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
public event PropertyChangedEventHandler PropertyChanged;
If I bind two textBoxes to the same public string, they reflect what is being typed in the other. Where am I going wrong then?
Your code is changing the sid backing field, not the ID property.
Therefore, the PropertyChanged event is never fired, and WPF never finds out about the change.
I have a drop down list on one form that populates a puzzle id code from a sql table.
when the user selects a puzzle code say "puzzle2" i want the next form(play:Form) to display this puzzle. At the moment i can only get it to display the 1st puzzle "puzzle1" on the page.
The database consists of puzzleID which is the puzzle type and puzzle which is the puzzle question itself.
public partial class Play : Form
{
public Play()
{
InitializeComponent();
SqlConnection conn = new SqlConnection("Data Source=LAURA-PC;Initial Catalog=Sudoku;Integrated Security=True");
conn.Open();
SqlCommand command = conn.CreateCommand();
command.CommandText = "Select puzzle from Puzzle";
command.CommandType = CommandType.Text;
SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
string[] tokens = ((string)reader[0]).Split(';');
textBox1.Text = tokens[0];
textBox2.Text = tokens[1];
textBox3.Text = tokens[2];
textBox4.Text = tokens[3];
textBox5.Text = tokens[4];
textBox6.Text = tokens[5];
textBox7.Text = tokens[6];
textBox8.Text = tokens[7];
textBox9.Text = tokens[8];
textBox10.Text = tokens[9];
textBox11.Text = tokens[10];
textBox12.Text = tokens[11];
textBox13.Text = tokens[12];
textBox14.Text = tokens[13];
textBox15.Text = tokens[14];
textBox16.Text = tokens[15];
}
conn.Close();
}
I know i need to implement some sort of of global variable from the drop down list in the previous form and then try filter that variable into Where statement? But im having no luck.
Thanks
You can make an static class as a common place to share objects. All classes can see this class and use its members.
public static class CommonClass
{
public static String puzzleCode ;
}
Also you can have a property on the second form to accept the puzzle id. Like this :
public class SecondForm : Form
{
private String _puzzleId ;
public String PuzzleId
{
get { return _puzzleId ; }
set { _puzzleId = value ; }
}
}
1. Passing variable to form.
Play frmPlay = new Play(puzzleId);
frmPlay.Show();
your Play class will be changed by this
public Play(int puzzleId)
{
//Unchanged code
command.CommandText = "Select puzzle from Puzzle where puzzleId = "+puzzleId;
//Unchanged code
}
2. Passing data through delegate
Add a delegate signature to form1 as below:
public delegate void delPassData(int puzzleId);
Play frmPlay= new Play ();
delPassData del=new delPassData(frmPlay.SetPuzzleId);
del( Convert.ToInt32(cmBxPuzzleId.SelectedValue));
frmPlay.Show();
**In Play form write this code**
private int m_PuzzleId;
public void SetPuzzleId(int puzzleId )
{
m_PuzzleId = puzzuleId;
}