I'm having some difficulties understanding how databases and SQL works. I'm trying to update a certain row in my database. I can remove a row, but when i use the InsertAt function, it is always appended to the end of my database. Also, it's assigned a new identifier key.
I would like to just edit what is already in there. No need for a new key, and I would like the edited row to stay where it was.
I've tried to strip down the code to show the the problem.
public partial class MainWindow : Window
{
System.Data.SqlClient.SqlConnection con;
System.Data.SqlClient.SqlDataAdapter da;
DataSet sessions;
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
con = new System.Data.SqlClient.SqlConnection();
sessions = new DataSet();
con.ConnectionString = "Data Source=.\\SQLEXPRESS;AttachDbFilename=C:\\Users\\md\\PokerDataBase.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
con.Open();
string sql = "SELECT * From Sessions";
da = new System.Data.SqlClient.SqlDataAdapter(sql, con);
da.Fill(sessions, "Sessions");
con.Close();
System.Data.SqlClient.SqlCommandBuilder cb;
cb = new System.Data.SqlClient.SqlCommandBuilder(da);
DataTable dt = sessions.Tables["Sessions"];
DataRow table = sessions.Tables["Sessions"].NewRow();
table[0] = "Some Data";
table[1] = "Some Data";
table[2] = "Some Data";
table[3] = 2;
table[4] = 3;
sessions.Tables["Sessions"].Rows[2].Delete();
sessions.Tables["Sessions"].Rows.InsertAt(table, 2);
da.Update(sessions, "Sessions");
}
}
Could anyone help me figure out what I'm doing wrong?
Error
You are creating a new row using
DataRow table = sessions.Tables["Sessions"].NewRow();
This will add new row to you database, it's not going to update a row.
Solution
To update a row you need to select that specific row, something like:
DataRow table = sessions.Tables["Sessions"].Rows[0];
then modify the row data and then update da.
This will the update existing row in your database.
Related
I have a DataBinding which works.
I would like to give my "Save" Button the function...
that it saves the TextBox.Text to the third character of a cell in the database with databinding code.
(Binding over the properties seems not to work)
Right now I am replacing the whole cell with this (working):
bindingSource.DataSource = list[index];
And this try is (not working):
list[index].CELL_NAME_A.Substring(2, 1) = "A";
Ignore the index.
But I wan't to pass the whole letter (TextBox.Text) only to the third character of that cell while ignoring the first two letters.
How do I do it?
You can try the following code to bind the third character of the cell in the database to the textbox.
DataSet dataSet = new DataSet();
DataTable table = new DataTable();
private void Form1_Load(object sender, EventArgs e)
{
string constr = #"connstr";
SqlConnection connection = new SqlConnection(constr);
connection.Open();
string sql = "select * from Student";
SqlDataAdapter dataAdapter = new SqlDataAdapter(sql, connection);
dataAdapter.Fill(dataSet);
table = dataSet.Tables[0];
table.TableName = "Student";
foreach (DataRow item in table.Rows)
{
item["Name"] = item["Name"].ToString().Substring(2, 1);
}
textBox1.DataBindings.Add(new Binding("Text", dataSet, "Student.Name"));
}
Result:
The search method is here:
private void textBox1_TextChanged(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Data Source=DESKTOP-HNR3NJB\\mysql;Initial Catalog=stock;Integrated Security=True");
SqlDataAdapter sda = new SqlDataAdapter("SELECT ProductName FROM [stock].[dbo].[Products]", con);
sda.Fill(dt);
dataGridView1.DataSource = dt;
dt.DefaultView.RowFilter = string.Format("ProductName LIKE '%{0}%'", textBox1.Text);
}
Now that does filter out the results in the table, but it adds columns like the picture below:
Search Results
Load data function (gets called as soon as the form is loaded:
public void LoadData()
{
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-HNR3NJB\mysql;Initial Catalog=stock;Integrated Security=True");
con.Open();
//reading data from sql
SqlDataAdapter sda = new SqlDataAdapter("SELECT * FROM [stock].[dbo].[Products]", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.Rows.Clear();
foreach (DataRow item in dt.Rows)
{
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = item["ProductID"].ToString();
dataGridView1.Rows[n].Cells[1].Value = item["ProductName"].ToString();
if ((bool)item["ProductStatus"])
{
dataGridView1.Rows[n].Cells[2].Value = "Active";
}
else
{
dataGridView1.Rows[n].Cells[2].Value = "Inactive";
}
dataGridView1.Rows[n].Cells[3].Value = item["Employee"].ToString();
dataGridView1.Rows[n].Cells[4].Value = item["CPU"].ToString();
dataGridView1.Rows[n].Cells[5].Value = item["RAM"].ToString();
dataGridView1.Rows[n].Cells[6].Value = item["SSD"].ToString();
dataGridView1.Rows[n].Cells[7].Value = item["HDD"].ToString();
dataGridView1.Rows[n].Cells[8].Value = item["WindowsVersion"].ToString();
dataGridView1.Rows[n].Cells[9].Value = item["Description"].ToString();
dataGridView1.Rows[n].Cells[10].Value = item["Type"].ToString();
}
con.Close();
}
Thanks
OK, so you're filling the datagridview elsewhere. You would just need to apply the rowfilter to the view to in the textbox_textchanged event
Where you're populating your current datagridview, ensure that you have your dt instantiated in a wider scope so that the textbox event can access it and then all you should have to do in your textchanged event is the following line:
dt.DefaultView.RowFilter = string.Format("ProductName LIKE '%{0}%'", textBox1.text);
This should then limit the rows to what is currently found. Here's an example of a demo database (you will have to change this to suit your needs)
DataTable dt; //declared outside a method so that multiple methods have access to it object.
private void Form1_Load(object sender, EventArgs e)
{
//Some other area where the datagridview is populated with more information
SqlConnection con = new SqlConnection(#"MyConnectionString");
con.Open();
SqlDataAdapter sda = new SqlDataAdapter("SELECT FirstName, LastName, Address, State FROM Employee", con);
dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
//all that should be needed to filter the datagridview to your condition
dt.DefaultView.RowFilter = string.Format("FirstName LIKE '%{0}%'", textBox1.Text);
}
Of course, you really need to switch to using statements so that the objects used are disposed of properly but this is to show more that the basic reason your grid is doing this is that you are applying another datasource into the grid and it doesn't know that you still want all the information you had prior just limited to rows that match your filter.
EDIT - FOR CLARIFICATION
Let's do this. In your loaddata code, remark out the entire for each loop. Add the following lines
datagridview1.columns.clear();
datagridview1.datasoure = dt;
This will hide your pre-existing columns for now without you having to do it manually.
And should show the grid with all the information from the query.
Then in your textchanged event remark all your code and replace it with the line I showed above that uses the DefaultView of the datatable (dt)
That should get you up and running. Once that's done, we can make a change to the query that will allow you to show 'Active'/'InActive' instead of the checkbox for the bit field.
Using the following code the first row in SQL is printed only, How can I print selected row from DataGridView in C# with SQL:
public partial class PrintScreen : Form
{
SqlConnection con = new SqlConnection(#"Server = TEST;DataBase=Registration;Integrated Security=true;");
SqlDataAdapter da;
DataTable dt = new DataTable();
public PrintScreen()
{
InitializeComponent();
da = new SqlDataAdapter("select * from data_graduation", con);
da.Fill(dt);
this.dataGridView1.DataSource = dt;
}
private void Print_ys_ar_cert_Click(object sender, EventArgs e)
{
Print_ys_ar_cert frm = new Print_ys_ar_cert();
da = new SqlDataAdapter("select * from data_graduation where ID_gra = '" + dataGridView1.CurrentRow.Cells[0].Value.ToString() + "'", con);
da.Fill(frm.RegistrationDataSet1.data_graduation);
frm.reportViewer2.RefreshReport();
frm.Show();
}
}
Currently you are passing value of Cells[0] of first row of the grid, you need to pass value of selected row:
if(dataGridView1.SelectedRows.Count>0)
{
var selectedValue = dataGridView1.SelectedRows[0].Cells[0].ToString();
//rest of code
}
Since you have loaded the row from database once, you don't need to load it again from database, you can simply add it to the data table which is data source of the report this way:
var row = ((DataRowView)(dataGridView1.SelectedRows[0].DataBoundItem)).Row;
frm.RegistrationDataSet1.data_graduation.Rows.Add(row.ItemArray);
//rest of code
I use visual studio 2012: c# winform. I have a datagridview in which 2 columns(Id and society) are created. the datagridview contains 25 records fetched my database.
I also added a button named "Action" to each row in datagridview
Note: In my phpmyadmin database, each society contains many service category and service types
My problem is:
I want that when a button "action" is pressed, all the service category and service type related to that society appear in the same or another datagridview.
Could you help me?
Try somthing like that, you must initiate this function with your main DataGridView, and you will have your "Cloned" DataGridView.
public DataGridView CloneDataGrid(DataGridView mainDataGridView)
{
DataGridView cloneDataGridView = new DataGridView();
if (cloneDataGridView.Columns.Count == 0)
{
foreach (DataGridViewColumn datagrid in mainDataGridView.Columns)
{
cloneDataGridView.Columns.Add(datagrid.Clone() as DataGridViewColumn);
}
}
DataGridViewRow dataRow = new DataGridViewRow();
for (int i = 0; i < mainDataGridView.Rows.Count; i++)
{
dataRow = (DataGridViewRow)mainDataGridView.Rows[i].Clone();
int Index = 0;
foreach (DataGridViewCell cell in mainDataGridView.Rows[i].Cells)
{
dataRow.Cells[Index].Value = cell.Value;
Index++;
}
cloneDataGridView.Rows.Add(dataRow);
}
cloneDataGridView.AllowUserToAddRows = false;
cloneDataGridView.Refresh();
return cloneDataGridView;
}
Hope This Help
If i understand your question correctly, you could use a cell content click event to refill your datatable with the filtered results.
I've done this on one of my forms (see below), however I havent used a phpmyadmin database, only sql, but the logic might be the same.
I should also note that I have the default cell selection as full row select.
For arguments sake, let's say the form shows products, so ProductID, ProductName and ProductType. When we click the button in the grid we want it to filter by the selected row's ProductType.
//First we declare a static string that can be accessed by the whole form
//and blank it so the form doesnt use a previous value.
public static string product_type = ""
//In the form load event, the gridview is populated - this could be moved to anywhere.
private void Form1_Load(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection("DB connection string");
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Products", conn);
SqlDataAdapter sqlDataAdap = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
sqlDataAdap.Fill(ds);
DataTable dt = new DataTable();
sqlDataAdap.Fill(dt);
conn.Close();
}
//In the cell contect click event we give it the ProductType
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
//Here we declare a var to identify that we're looking at the row
var row = dataGridView1.CurrentRow.Cells;
//Now we set the string we declared earlier
product_type = Convert.ToString(row["ProductType"].Value);
//Now we repeat the grid script with a parameter which uses our string from above
SqlConnection conn = new SqlConnection("DB connection string");
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Products WHERE ProductType = #ProductType", conn);
sc.Parameters.Add("#ProductType", SqlDbType.Int).Value = product_type;
SqlDataAdapter sqlDataAdap = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
sqlDataAdap.Fill(ds);
DataTable dt = new DataTable();
sqlDataAdap.Fill(dt);
conn.Close();
}
You could then just add a button which repeats the script from the form load event when clicked to return the grid to it's non-filtered state.
Hope this helps.
I have a WPF Browserapplication which gets data stored on a SQL Server, stores it in a DataTable and displays it in a DataGrid. Now I want to have a TextBox where you can search entries in the DataTable but when I load the Application I'm getting an error telling me, that the row [Company] cannot be found.
I think the problem is, that the DataTable isn't yet filled when the filter is being applied to the DataTable. Can someone please give me a hint how to make this working?
DataTable dt = new DataTable();
public Page1()
{
InitializeComponent();
showSQLData();
}
private void showSQLData()
{
string sqlConnectionString = #"blabla";
string sqlCommandString = "SELECT * FROM Excel_import";
using (SqlConnection sqlConnection = new SqlConnection(sqlConnectionString))
{
SqlCommand cmd = new SqlCommand(sqlCommandString, sqlConnection);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(dt);
dataGridSQLData.ItemsSource = dt.DefaultView;
}
}
private void textBoxSearch_TextChanged(object sender, TextChangedEventArgs e)
{
dt.DefaultView.RowFilter = string.Format("Company LIKE '%{0}%'", textBoxSearch.Text);
}
Based on you latest comment I would guess that textBoxSearch_TextChanged is being fired from within the InitializeComponent() call. You could check that dt.Rows.Count > 0 in textBoxSearch_TextChanged and return if that condition is not met.