Saving data to database from new form - c#

I have a program that uses a dataGridView on Form1 to display data from a SQL Server database.
The user can also edit and save data back to the DB from the Form1 dataGridView.
However, I also have a search function that will pop up a new form and display the results of the search.
I want users to be able to save directly from the new window but at the moment it is only updating the data in the Form1 dataGridView.
This is what I am using to display the results of the Search.
private void ResultsFunc()
{
var ColumnToSearch = comboBox1.Text;
if (textBox1.Text.Length == 0)
{
var toSearchBy = listBox1.SelectedItem.ToString();
aSH_ORDER_DBDataSet1.ASH_PROD_ORDERS.DefaultView.RowFilter = ColumnToSearch + " = " + "'" + toSearchBy + "'";
}
else if (textBox1.Text.Length > 0)
{
var toSearchBy = textBox1.Text;
aSH_ORDER_DBDataSet1.ASH_PROD_ORDERS.DefaultView.RowFilter = ColumnToSearch + " = " + "'" + toSearchBy + "'";
}
Form2 resultsForm = new Form2();
resultsForm.dataGridView2.DataSource = aSH_ORDER_DBDataSet1.ASH_PROD_ORDERS.DefaultView;
resultsForm.Show();
}
This is what I am using to try save the data from Form2:
private void button1_Click(object sender, EventArgs e)
{
aSH_PROD_ORDERSTableAdapter.Update(aSH_ORDER_DBDataSet1);
}
How can I get the info entered in Form2 to save directly to the database rather than just update the dataGridView in Form1?

Have you tried SqlBulkCopy, it can update data to SQLServer
but make sure you have the necessary columns and schema in the datatable
protected void Button1_Click(object sender, EventArgs e)
{
try
{
string cs = ConfigurationManager.ConnectionStrings["SchoolConnectionString"].ConnectionString;
using (SqlConnection sqlConn = new SqlConnection(cs))
{
DataSet ds = aSH_ORDER_DBDataSet1;
DataTable dtStudentMaster = ds.Tables["Student"];
// ds.Tables["Student"], if aSH_ORDER_DBDataSet1 has multiple tables in it specify the table name else ds.Tables[0] is fine
sqlConn.Open();
using (SqlBulkCopy sqlbc = new SqlBulkCopy(sqlConn))
{
sqlbc.DestinationTableName = "StudentMaster";
// StudentMaster - Table need to be updated in SQLServer
// Make sure you have the similar column names and datatype in both datatable and sql server table
sqlbc.ColumnMappings.Add("Name", "Name");
sqlbc.ColumnMappings.Add("Phone", "Phone");
sqlbc.ColumnMappings.Add("Address", "Address");
sqlbc.ColumnMappings.Add("Class", "Class");
sqlbc.WriteToServer(dtStudentMaster);
Response.Write("Bulk data stored successfully");
}
}
}
catch (Exception ex)
{
throw ex;
}
}

Related

Updating/saving data to an SQL database table using c# winforms

I'll start off by saying that I'm pretty inept at coding (have yet to learn how to utilize classes and how they work in depth), and that I've never worked with sql before doing this project.
The idea here is that you connect to an sql database, after which a datagridview element gets filled with data from a table called TABLE_1 by default. The user should then be able to input, delete and save data.
The first two work operations work perfectly, but the saving is the problem. I've banged my head against a wall for about 4 days trying to get the saving to work, but I just cant get it to do so. The saving is done with the method Button3_click.
Any insight as to what I should do?
Is the main chunk of the code where you connect the part where I'm
messing up?
//initialize the classes I guess, on some youtube guides they did so
SqlConnection con;
DataSet ds;
SqlDataAdapter a;
DataTable t;
SqlCommandBuilder scb;
static string tablename = "TABLE_1";
string constring;
//connect button
private void button1_Click(object sender, EventArgs e)
{
try
{
//connect using info from textboxes, connection is ok
constring = "server=" + Server.Text + ";database=" + DB.Text + ";UID=" + UID.Text + ";password=" + Password.Text;
SqlConnection con = new SqlConnection(constring);
con.Open();
DataSet ds = new DataSet();
Save.Enabled = true;
//check if table name is empty, if so default to TABLE_1
if (textBox1.Text != "")
{
tablename = textBox1.Text;
}
else
{
tablename = "TABLE_1";
}
a = new SqlDataAdapter("SELECT * FROM " + tablename, con);
DataTable t = new DataTable();
a.Fill(t);
datagrid.DataSource = t;
//
label5.Text = Server.Text;
con.Close();
}
catch(Exception es)
{
MessageBox.Show(es.Message);
}
}
//save button
private void button3_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(constring);
con.Open();
DataSet ds = new DataSet();
DataTable t = new DataTable();
a.TableMappings.Add(tablename, "t");
scb = new SqlCommandBuilder(a);
a.Update(t);
con.Close();
}
Use the following example which sets up the adapter, dataset and table name as private variables.
Also, I recommend to never use one letter variable names as a) it's difficult to debug b) when getting into more lines of code it's going to be difficult to know what a variable is for.
Next up, using SELECT *, it' unknown if you have setup a auto-incrementing primary key which is needed to perform updates. In the example below, Id is auto-incrementing.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace WindowsFormsDataAdapterExample
{
public partial class Form1 : Form
{
private SqlDataAdapter _companiesSqlDataAdapter;
private DataSet _companiesDataSet;
private string _tableName = "Companies";
public Form1()
{
InitializeComponent();
Shown += OnShown;
}
private void OnShown(object sender, EventArgs e)
{
_companiesDataSet = new DataSet();
_companiesSqlDataAdapter = new SqlDataAdapter(
"SELECT Id, FirstName, LastName, PhoneNumber, City FROM dbo.Companies;",
"Data Source=.\\sqlexpress;Initial Catalog=ForumExample;" +
"Integrated Security=True");
var builder = new SqlCommandBuilder(_companiesSqlDataAdapter);
_companiesSqlDataAdapter.Fill(_companiesDataSet, _tableName);
dataGridView1.DataSource = _companiesDataSet.Tables[_tableName];
}
private void SaveButton_Click(object sender, EventArgs e)
{
_companiesSqlDataAdapter.Update(_companiesDataSet, _tableName);
}
}
}

c# (vbs-15) how to fill datagrid and provide links

Sorry guys, but am new to c# and vbs. what am trying to do is to fill datagrid or any equivalent then i need to provide click-able buttons/links to each row.
When user click the button, the app should pass the row-id clicked to new (another) form.
...
p.textquery = "SELECT * FROM members ORDER BY member_id DESC LIMIT 250";
SQLiteConnection m_dbConnection = new SQLiteConnection("Data Source=" + p.dbname() + ";Version=3;");
m_dbConnection.Open();
try
{
SQLiteCommand command = new SQLiteCommand(p.textquery, m_dbConnection);
SQLiteDataReader reader = command.ExecuteReader();
bool rows = reader.HasRows;
if (rows)
{
while (reader.Read())
{
patient_id = reader["patient_id"].ToString();
// Here i need to show results to user but the user should have a button to select the row
}
return;
}
else
{
p.alert("You do not have members in the system");
return;
}
}
catch
{
p.alert("SQL has error - (database error)");
return;
}
...
The problem is how to provide datagrid or any equivalent which has button where user can click to view the record.
Your help is highly appreciated
EDIT
private void dataGridView1_CellContentClick_2(object sender, DataGridViewCellEventArgs e)
{
plugin p = new plugin();
try {
if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewButtonCell)
{
//I need the value of the column here member_id is only showing the rowindex and columnindex now i need the value
p.alert(dataGridView1.Rows[e.ColumnIndex].Cells[e.ColumnIndex].ToString());
}
else
{
p.alert(dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].ToString() + " on else");
}
}
catch (Exception v)
{
//p.alert("Header clicked ");
}
}
EDIT - ANSWER
dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString();
where Cells[2] is the targeted cell
Drag and drop a datagridview from the toolbox to the window, Add All the columns in your data table to it using properties--> columns in that add a button column or a link column.
Bind data to grid as below
DataTable dtMembers = new DataTable();
p.textquery = "SELECT * FROM members ORDER BY member_id DESC LIMIT 250";
SQLiteConnection m_dbConnection = new SQLiteConnection("Data Source=" + p.dbname() + ";Version=3;");
try
{
SQLiteDataAdapter da = new SQLiteDataAdapter(p.textquery,m_dbConnection);
m_dbConnection.Open();
da.Fill(dtMembers);
m_dbConnection.Close();
if(dtMembers.Rows.Count > 0)
dgvMembers.DataSource = dtMembers;
else
p.alert("You do not have members in the system");
}
catch
{
p.alert("SQL has error - (database error)");
return;
}
Implement DataGridView cell content click
private void dgvMembers_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if(dgvMembers.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewButtonCell)
{
//Write your code here
}
}
See below I have text property where I wrote click here, that's where you need to put button name

Update datagridview from SQL in the form close event

I have a form with a dataGridView1 that is updated from SQL database.
What i am trying to do is: when the user presses the Close button I am checking a variable and if condition is true then I cancel the from close (e.Cancel = true;) and i want to display some data in the datagrid.
Whatever I do the grid is not updating. I am calling a "private void update()" to update the grid from SQL but after I cancel the form close event but it does not seem to work.
I have tried refreshing the form, refreshing the datagrid with no result.
After the form_Close even finishes, and the datagrid is empty, if i press a button that calls the same "private void update()" it works and the data is shown in the datagrid.
Thank you for your help.
EDIT1: to give you more details
I tried the code on FormClosing but I get no result.
The code I'm using is:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
getdata_fromSQL();//this private void gets some data from sql into the datagrid
if (dataGridView1.RowCount > 0)//check if i have at least one row retreved
{
// Cancel the Closing event and tell the user
MessageBox.Show("Please check the data before leaving.");
e.Cancel = true;
getdata_fromSQL();// retrieve the data again for the user to see (this part is not working
}
}
This is how the data is retrieved.
private void getdata_fromSQL()
{
SqlConnection con = new SqlConnection("connection string"); //defining connection
con.Open();
string sql_command = "Select * from Test_Table where [Check] is null";
SqlCommand command = new SqlCommand(sql_command, con); // defining the command
DataSet set = new DataSet("SQL_table");
SqlDataAdaptersda = new SqlDataAdapter(command); //defining the adapter and make it accept changes
sda.AcceptChangesDuringFill = true;
sda.AcceptChangesDuringUpdate = true;
set.Clear(); //just to make sure my adapter is empty
cmdBuilder = new SqlCommandBuilder(sda); //creating the command builder so I can save the changes
sda.Fill(set, "SQL_table"); // fill the dataset
dataGridView1.DataSource = set;
dataGridView1.DataMember = "SQL_table"; //fill datagrid
dataGridView1.CellValueChanged -= dataGridView1_CellValueChanged;
dataGridView1.CellValueChanged += dataGridView1_CellValueChanged; //look for cell value changed (I am using this in other scope)
}
After I cancel the close and try to update the datagrid again, it remains blank.
EDIT2: #Gami
your code does this:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (i == 1)
{
MessageBox.Show("Hello");
e.Cancel = true;
getRefresh();
}
}
and your refresh is this:
private void getRefresh()
{
SqlConnection con = new SqlConnection(#"user id=testuser;" +
"password=testpass;Data Source=SERVER;" +
// "Trusted_Connection=yes;" +
"Initial Catalog=Partner_database; " +
"connection timeout=30"); //defining connection
con.Open();
SqlCommandBuilder cmdBuilder;
string sql_command = "Select * from Test_table where [Check] is null";
SqlCommand command = new SqlCommand(sql_command, con); // defining the command
DataSet set = new DataSet("SQL_table");
SqlDataAdapter sda = new SqlDataAdapter(command); //defining the adapter and make it accept changes
sda.AcceptChangesDuringFill = true;
sda.AcceptChangesDuringUpdate = true;
set.Clear(); //just to make sure my adapter is empty
cmdBuilder = new SqlCommandBuilder(sda); //creating the command builder so I can save the changes
sda.Fill(set,"SQL_table"); // fill the dataset
dataGridView1.DataSource = set;
dataGridView1.DataMember = "SQL_table"; //fill datagrid
}
My code is the one above. We are both using the FormClosing event, we both cancel the close process, and then call the refresh.
This is the SQL table:
This is the datasource for my datagrid:
Try to write code in Form1_FormClosing() event of form
example is
namespace canceldemo
{
public partial class Form1 : Form
{
int i = 1;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (i == 1)
{
MessageBox.Show("Hello");
e.Cancel = true;
}
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = (i+10).ToString();
}
}
}
I have found the issue.
Looks like it was a mistake on my side, I still don't know why is not working the way it is, but know the cause.
I am using code to get the logged user name from Windows, and when i filter the SQL table i filter on the user as well.
This is the code to retrieve the user:
private string getUserDisplayName()
{
var username = new StringBuilder(1024);
uint userNameSize = (uint)username.Capacity;
// try to get display name and convert from "Last, First" to "First Last" if necessary
if (0 != GetUserNameEx(3, username, ref userNameSize))
return Regex.Replace(username.ToString(), #"(\S+), (\S+)", "$2 $1");
// get SAM compatible name <server/machine>\\<username>
if (0 != GetUserNameEx(2, username, ref userNameSize))
{
IntPtr bufPtr;
try
{
string domain = Regex.Replace(username.ToString(), #"(.+)\\.+", #"$1");
DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, domain);
DomainController dc = DomainController.FindOne(context);
if (0 == NetUserGetInfo(dc.IPAddress,
Regex.Replace(username.ToString(), #".+\\(.+)", "$1"),
10, out bufPtr))
{
var userInfo = (USER_INFO_10)Marshal.PtrToStructure(bufPtr, typeof(USER_INFO_10));
return Regex.Replace(userInfo.usri10_full_name, #"(\S+), (\S+)", "$2 $1");
}
}
finally
{
NetApiBufferFree(out bufPtr);
}
}
return String.Empty;
}
In my FormClosing block i am calling this private void and use this as filter to sql.
user_name = getUserDisplayName();
string sql_command = "Select * from Test_table where [Check] is null and [User Name] = '" + user_name + "'";
When removing the getUserDisplayName() call it works. When i call it it does not refresh the grid even if it runs with no error.
Does it cut my connections when i press the close button? I think this is another question and here is off topic.

C# refresh DataGridView when updating or inserted on another form

I have 2 forms which are form A and form B,
form A allowes user to insert and update student information.
form b is only a DataGridView and button there.
When I insert student on form A, then I go to form B, the new student did not show on the DataGridView , and if I rerun the program, the new student will appear in form B.
I tried using this on button on form b
datagridview1.refresh();
datagridview1.update();
but it's still not working.
Edited:
My code for inserting a worker
cmd = new OleDbCommand("insert into FWINFOS (ID,Name,Gender,DateOfBirth,Race,WorkingPlace,PassportNO,DateOfExpire,[Position],Photo) values('" + textBox5.Text + "','" + textBox1.Text + "','" + textBox2.Text + "','" + dateTimePicker1.Value + "','" + textBox3.Text + "','" + textBox4.Text + "','" + textBox6.Text + "','" + dateTimePicker2.Value + "',#Position,#Photo)", con);
cmd.Parameters.AddWithValue("#Position", comboBox1.SelectedText.ToString());
conv_photo();
con.Open();
int n = cmd.ExecuteNonQuery();
//cmd.ExecuteNonQuery();
con.Close();
if (n > 0)
{
MessageBox.Show("Inserted");
loaddata();
rno++;
}
else
MessageBox.Show("No Insert");
}
my Datagridview1(Form2) doesn't automatically update when I inserted a new worker. But if I rerun the application, the new worker appears.
// Form A
public void loaddata()
{
//do what you do in load data in order to update data in datagrid
}
then on Form B define:
// Form B
FormA obj = (FormA)Application.OpenForms["FormA"];
private void button1_Click(object sender, EventArgs e)
{
obj.loaddata();
datagridview1.Update();
datagridview1.Refresh();
}
DataGridView.Refresh and And DataGridView.Update are methods that are inherited from Control. They have to do with redrawing the control which is why new rows don't appear.
My guess is the data retrieval is on the Form_Load. If you want your Button on Form B to retrieve the latest data from the database then that's what you have to do whatever Form_Load is doing.
A nice way to do that is to separate your data retrieval calls into a separate function and call it from both the From Load and Button Click events.
For datagridview in C#, use this code
con.Open();
MySqlDataAdapter MyDA = new MySqlDataAdapter();
string sqlSelectAll = "SELECT * from dailyprice";
MyDA.SelectCommand = new MySqlCommand(sqlSelectAll, con);
DataTable table = new DataTable();
MyDA.Fill(table);
BindingSource bSource = new BindingSource();
bSource.DataSource = table;
dataGridView1.DataSource = bSource;
con.Close();
It works for show new records in the datagridview.
for refresh data gridview in any where you just need this code:
datagridview1.DataSource = "your DataSource";
datagridview1.Refresh();
my datagridview is editonEnter mode . so it refresh only after i leave cell or after i revisit and exit cell twice.
to trigger this iimedately . i unfocus from datagridview . then refocus it.
this.SelectNextControl(dgv1,true,true,false,true);
Application.DoEvents(); //this does magic
dgv1.Focus();
putting a quick example, should be a sufficient starting point
Code in Form A
public event EventHandler<EventArgs> RowAdded;
private void btnRowAdded_Click(object sender, EventArgs e)
{
// insert data
// if successful raise event
OnRowAddedEvent();
}
private void OnRowAddedEvent()
{
var listener = RowAdded;
if (listener != null)
listener(this, EventArgs.Empty);
}
Code in Form B
private void button1_Click(object sender, EventArgs e)
{
var frm = new Form2();
frm.RowAdded += new EventHandler<EventArgs>(frm_RowAdded);
frm.Show();
}
void frm_RowAdded(object sender, EventArgs e)
{
// retrieve data again
}
You can even consider creating your own EventArgs class that can contain the newly added data. You can then use this to directly add the data to a new row in DatagridView
I wanted to do the exactly same thing.
public static bool update = false;
Timer t = null;
private void RefreshTable()
{
t = new Timer();
t.Interval = 1000;
t.Tick += new EventHandler(t_Tick);
t.Enabled = true;
}
void t_Tick(object sender, EventArgs e)
{
if (update)
{
dataGridView.Rows.Clear();
dataGridView.Refresh();
setCustomerDetailsTable();
update = false;
}
}
I am using a static variable in the form that contains the dataGridView and access it from form A. when user insert or update details I set the update variable true so that when the next time timer ticks the table updates and set the
update as false. That prevent it from updating everytime timer ticks. The setCustomerDetailsTable() is the function that initialy loads the data on Form_Load in my case. I am sure this is not the best way. However I am using this timer to show the clock on the UI as well. So I assign it this task as well. When I call RefreshTable() on Form_Load it does what I wanted.
Create a small function and use it anywhere
public SqlConnection con = "Your connection string";
public void gridviewUpdate()
{
con.Open();
string select = "SELECT * from table_name";
SqlDataAdapter da = new SqlDataAdapter(select, con);
DataSet ds = new DataSet();
da.Fill(ds, "table_name");
datagridview.DataSource = ds;
datagridview.DataMember = "table_name";
con.Close();
}

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