update data from MySQL - c#

hello i create a program that can add/edit/delete data from database
i've done the Add data process but my problem is i cannot do the Edit and Delete data.
whenever i click the button Edit the Error message appear
here is the error message:
"Dynamic SQL generation for the UpdateCommand is not supported againts a SelectedCommand that does not return any key column information"
and this is my code for button edit
try
{
string contactNumVal = txtCcontact.Text;
if (contactNumVal.Length < 11)
{
MessageBox.Show("The Contact Number must have 11 digit");
}
else
{
DialogResult dw;
dw = MessageBox.Show("Are you sure you want to Edit this data", "Confirm Deletion", MessageBoxButtons.YesNo);
if (dw == DialogResult.Yes)
{
string MyConString = "SERVER=localhost;" +
"DATABASE=prototype_db;" +
"UID=root;";
MySqlConnection connection = new MySqlConnection(MyConString);
connection.Open();
MySqlCommand command = connection.CreateCommand();
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter("Select ClientName,ClientAddress,ClientContactNo,ClientContactPerson from client_profile where ClientName like '%"+txtCname.Text+"%'" +" ",connection);
da.Fill(dt);
dt.Rows[0].BeginEdit();
dt.Rows[0][0] = txtCname.Text;
dt.Rows[0][1] = txtCaddress.Text;
dt.Rows[0][2] = txtCcontact.Text;
dt.Rows[0][3] = txtCconPer.Text;
dt.Rows[0].EndEdit();
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
da.Update(dt);
connection.Close();
MessageBox.Show("Data is now updated");
}
}
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
thanks for the Answers

The DataAdapter needs to get information on the Primary Key of your table if you want it to be able to execute UPDATE and DELETE (no problems with SELECT and INSERT) but your query doesn't return this information because the Client_ID field is not enclosed in your command text
So you should change your code to
using(MySqlConnection connection = new MySqlConnection(MyConString))
{
connection.Open();
DataTable dt = new DataTable();
using(MySqlDataAdapter da = new MySqlDataAdapter("Select Client_ID, ClientName, " +
"ClientAddress, ClientContactNo,ClientContactPerson " +
"from client_profile where ClientName like #cname",connection))
{
da.SelectCommand.Parameters.AddWithValue("#cname", "%" + txtCname.Text +"%");
da.Fill(dt);
}
}
Notice also that I have removed the string concatenation of the ClientName value used in the WHERE condition. Use always parameters and not text directly typed by your user when you build sql commands. In this way you avoid SQL Injection problems and parsing problems (single quotes inside txtCName textbox would break the string concatenation)
After adding the Client_ID as above you should also change the index used to update the row values
dt.Rows[0][1] = txtCname.Text;
dt.Rows[0][2] = txtCaddress.Text;
dt.Rows[0][3] = txtCcontact.Text;
dt.Rows[0][4] = txtCconPer.Text;

Related

Maintaining state of checkboxes while filtering record using textbox

I am working on a C# windows application to populate records from SQL Server to data grid view, with dynamic checkbox facility in each row. I want to select selected rows for some purpose via checkbox of that particular row. Till now I successfully achieve my target, but I'm facing a minor issue regarding saving a checked status.
For example I want to check only those records whose Name = Max. I have a textbox in that textbox I call text change event with like Query:
try
{
SqlCommand cmd = null;
SqlConnection con = null; Ranks rank = new Ranks();
con = new SqlConnection(cs.DBcon);
con.Open();
cmd = con.CreateCommand();
cmd.CommandText = "Select * from Records where Name like #Name order by Pno";
cmd.Parameters.AddWithValue("#Name", "%" + FilterByNameTextbox.Text.Trim() + "%");
SqlDataAdapter adapter1 = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adapter1.Fill(dt);
dataGridView1.DataSource = dt;
Make_fields_Colorful();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
If I write Max in filter by name textbox it would return 3 records with name starts with max using like query as I mention code above. So I only check 2 records out of 3 using dynamic checkbox, till now my code runs perfectly. Now I want to check records which name starts from Ali, now when I write ali in my filter by name textbox it will return rows where name like ali , but problem comes here it will remove my previous checked records, so how I would able to save checked records for both max and ali's rows:
Code for adding dynamic checkboxes in each row
DataGridViewCheckBoxColumn checkBoxColumn = new DataGridViewCheckBoxColumn();
checkBoxColumn.Name = "checkBoxColumn";
checkBoxColumn.DataPropertyName = "Report";
checkBoxColumn.HeaderText = "Report";
dataGridView1.Columns.Insert(10, checkBoxColumn);
dataGridView1.RowTemplate.Height = 100;
dataGridView1.Columns[10].Width = 50;
Images:
Image 1
Image 2
I suggest you achieve this by caching selected rows, first you should have a list of cached rows:
List<DataGridViewRow> CachedRows = new List<DataGridViewRow>();
then add event handler on cell value change like the following:
dataGridView1.CellValueChanged += view_CellValueChanged;
and the handler should check if the column changed is the checkbox and checked, should be something like the following:
try
{
if(e.ColumnIndex == indexOfCheckBoxColumn)
{
if((bool)dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value == true)
{
CachedRows.Add((DataGridViewRow)dataGridView1.Rows[e.RowIndex].Clone());
}
else if (CachedRows.Contains(dataGridView1.Rows[e.RowIndex]))//Validate if this works, if not you should associate each row with unique key like for example (id) using a dictionary
{
CachedRows.Remove(dataGridView1.Rows[e.RowIndex]);
}
}
}
catch(Exception ex)
{
}
then after the filter changes, re-add the cached rows again, so code becomes:
try
{
SqlCommand cmd = null;
SqlConnection con = null; Ranks rank = new Ranks();
con = new SqlConnection(cs.DBcon);
con.Open();
cmd = con.CreateCommand();
cmd.CommandText = "Select * from Records where Name like #Name order by Pno";
cmd.Parameters.AddWithValue("#Name", "%" + FilterByNameTextbox.Text.Trim() + "%");
SqlDataAdapter adapter1 = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
adapter1.Fill(dt);
dataGridView1.DataSource = dt;
//add folowing
if (CachedRows.Any())
{
dataGridView1.Rows.AddRange(CachedRows.ToArray());
CachedRows.Clear();
}
Make_fields_Colorful();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
}

How do I fix the error "UpdateCommand has affected 0 of 1 expected entries."?

Used by:
- MSAccess 2016.
- Autoincrement "ID" is formed in the database table.
- DevExpress.
- gridControl. 
After I add a new entry to "gridControl1" I need to add an "ID" from the database.
Scenario_1:
- User. Fills the required field;
- User. Shifts focus to "gridControl1";
- The program. Adds a new entry to "gridControl1" - "Record_1";
- The program. Using the Row_Changed event, we add the entry "Record_1 "to the" database ";
- The program. Get ID "Record_1" from the database;
- The program. Updates the ID in the "DataTable" for the new entry "Record_1";
After executing the script "Scenario_1" the user tries to update any field of the new record.
Scenario_2:
- User. Changes the entry field "Record_1";
- User. Shifts focus to another entry;
- The program. Produces the error "UpdateCommand has affected 0 of 1 expected entries.";
How do I fix the error "UpdateCommand has affected 0 of 1 expected entries."?
added
State when an error occurs
public void connect()
{
string catBD = #"z:\vs\csharp\prb\718\01_pr\01_pr\01_pr\718.01.01.accdb";
string conBD = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}", catBD);
connection = new OleDbConnection(conBD);
connection.Open();
string query1 = "SELECT * FROM TableGrid_00";
OleDbCommand cmd1 = new OleDbCommand(query1, connection);
dt = new DataTable();
try
{
adapter = new OleDbDataAdapter(cmd1);
cmdBuilder = new OleDbCommandBuilder(adapter);
adapter.UpdateCommand = cmdBuilder.GetUpdateCommand();
adapter.InsertCommand = cmdBuilder.GetInsertCommand();
}
catch (Exception ex)
{
string s = ex.Message;
throw;
}
adapter.Fill(dt);
dt.RowChanged += new DataRowChangeEventHandler(Row_Changed);
}
private void Row_Changed(object sender, DataRowChangeEventArgs e)
{
adapter.Update(dt);
string SearchByColumn = "ID is null";
DataRow[] hasRows = dt.Select(SearchByColumn);
if (hasRows.Length != 0)
{
string query = "SELECT MAX(ID) FROM TableGrid_00";
OleDbCommand com;
OleDbDataReader dataReader;
com = new OleDbCommand(query, connection);
dataReader = com.ExecuteReader();
dataReader.Read();
int resultQuery = dataReader.GetInt32(0);
hasRows[0]["ID"] = resultQuery;
dataReader.Close();
}
else
{
}
}

Error in gridview trying to show data of only the current user

The C# code:
string str = "Data Source=(LocalDB)\\MSSQLLocalDB;";
str += "AttachDbFilename=|DataDirectory|DinoData.mdf;";
str += "Integrated Security= True";
SqlConnection c;
c = new SqlConnection(str);
if (Show.Text == "all" || Show.Text == "All" || Show.Text == "all table" || Show.Text == "All table" || Show.Text == "All Table" || string.IsNullOrWhiteSpace(Show.Text))
{
DataTable dt = new DataTable();
String req;
req = "SELECT * FROM [User] Where Username = "+Session["CurentUserid"];
SqlDataAdapter da = new SqlDataAdapter(req, c);
da.Fill(dt);
datagrid.DataSource = dt;
datagrid.DataBind();
}
else
{
if (!string.IsNullOrWhiteSpace(Show.Text))
{
DataTable dt = new DataTable();
String req;
req = Show.Text+ " Where Username = " + Session["CurentUserid"];
SqlDataAdapter da = new SqlDataAdapter(req, c);
da.Fill(dt);
datagrid.DataSource = dt;
datagrid.DataBind();
}
}
The error:
An exception of type 'System.Data.SqlClient.SqlException' occurred in
System.Data.dll but was not handled in user code
Additional information: Invalid column name 'Niss'.
Please help, Niss is the id of one of my users
This is a classical error caused by not using a parameterized query. You have forgotten to put the username value between single quotes so your Niss user has been confused as a column name
req = "SELECT * FROM [User] Where Username = #user";
SqlDataAdapter da = new SqlDataAdapter(req, c);
da.SelectCommand.Parameters.Add("#user", SqlDbType.NVarChar).Value = Session["CurentUserid"];
da.Fill(dt);
More in depth: UserName is a text column and thus if you want to search a value on this column you need to put the value between single quotes.
However fixing the problem adding a couple of quotes
Where Username = '"+Session["CurentUserid"] + "'"
just changes the problem because if you have a user with a single quote in its user name you are facing again a syntax error. The only correct way is to use a parameterized query as I have shown.
I leave the discussion about Sql Injection and all the problems you could face in your code in the else part (where you use a whole textbox to build your query to this well known answer

Error : Update requires a valid UpdateCommand when passed DataRow collection with modified rows

I am using Paging to show data in datagridview, but when i try to Update any data with updatebutton data should be updated In datagridview as well as in database.
But I get this error:
Update requires a valid UpdateCommand when passed DataRow collection
with modified rows
which happens on this line:
adp1.Update(dt);//here I am getting error
Below is the code
public partial class EditMediClgList : Form
{
public EditMediClgList()
{
InitializeComponent();
try
{
con = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db1.mdb");
con.Open();
}
catch (Exception err)
{
MessageBox.Show("Error:" +err);
}
cmd1 = new OleDbCommand("Select * from MedicalColeges order by MedicalClgID", con);
ds = new DataSet();
adp1 = new OleDbDataAdapter(cmd1);
adp1.Fill(ds, "MedicalColeges");
dataGridView1.DataSource = ds;
// Get total count of the pages;
this.CalculateTotalPages();
// Load the first page of data;
this.dataGridView1.DataSource = GetCurrentRecords(1, con);
}
private void CalculateTotalPages()
{
int rowCount = ds.Tables["MedicalColeges"].Rows.Count;
this.TotalPage = rowCount / PageSize;
if (rowCount % PageSize > 0) // if remainder is more than zero
{
this.TotalPage += 1;
}
}
private DataTable GetCurrentRecords(int page, OleDbConnection con)
{
dt = new DataTable();
if (page == 1)
{
cmd2 = new OleDbCommand("Select TOP " + PageSize + " * from MedicalColeges ORDER BY MedicalClgID", con);
// CurrentPageIndex++;
}
else
{
int PreviouspageLimit = (page - 1) * PageSize;
cmd2 = new OleDbCommand("Select TOP " + PageSize +
" * from MedicalColeges " +
"WHERE MedicalClgID NOT IN " +
"(Select TOP " + PreviouspageLimit + " MedicalClgID from MedicalColeges ORDER BY MedicalClgID) ", con); // +
//"order by customerid", con);
}
try
{
// con.Open();
this.adp1.SelectCommand = cmd2;
this.adp1.Fill(dt);
txtPaging.Text = string.Format("page{0} of {1} pages", this.CurrentPageIndex, this.TotalPage);
}
finally
{
// con.Close();
}
return dt;
}
private void button1_Click(object sender, EventArgs e)
{
try
{
adp1.Update(dt);//here I am getting error
}
catch (Exception err)
{
MessageBox.Show(err.Message.ToString());
}
}
}
You have Created the OleDbDataAdapter with a Select command only:
adp1 = new OleDbDataAdapter(cmd1);
OleDbDataAdapter requires valid Update, Insert, Delete commands to be used to save the data like this:
adp1.Update(dt);//here I am getting error
You just need to use a OleDbCommandBuilder that will generate the commands for you:
adp1 = new OleDbDataAdapter();
adp1.SelectCommand = cmd1; // cmd1 is your SELECT command
OleDbCommandBuilder cb = new OleDbCommandBuilder(adp1);
EDIT
Since you change the Select command of the OleDbDataAdapter at runtime for paging, what your need is to initialize each time you save data:
private void button1_Click(object sender, EventArgs e)
{
try
{
adp1.SelectCommand = cmd1; // cmd1 is your SELECT command
OleDbCommandBuilder cb = new OleDbCommandBuilder(adp1);
adp1.Update(dt); //here I hope you won't get error :-)
}
catch (Exception err)
{
MessageBox.Show(err.Message.ToString());
}
}
It could be that you are missing Primary Key in the table. You need to make sure primary key is set on a column in your data base table.
I had to alter my (incrementing) index column to the primary key of my table (as Eaint suggest). After this, I had to pull up the DataSet.xsd in designer view, right click on the visual DataTable object and select configure. When the TableAdapter Configuration Wizard opened, I clicked the Advanced Options button. I checked the Generate Insert, Update and Delete statements checkbox then OK and Finish. After this (still in designer view), I selected the visual TableAdapter object which gave me all the full properties. The SQL was autogenerated. Took a while for me to track this down, so I hope it helps someone.
Thanks to "#Chris" the code above works for me.
I needed to specify the Database Table name that will be updated when I Update.
You can read more about that here:
DataAdapter: Update unable to find TableMapping['Table'] or DataTable 'Table'
// This Adapter and Dataset are used for Populating my datagridview,
// so I use them also when I need to Update the Datagridview
SqlDataAdapter kundeTlfAdapter;
DataSet kundeTlfDataSet;
try
{
SqlConnection connection = new SqlConnection("Data source=BG-1-PC\\SQLEXPRESS; Database = Advokathuset; User Id = abc; Password = abc;");
SqlCommand cmd1 = new SqlCommand("Select* From Kunde_Tlf", connection);
SqlCommandBuilder builder = new SqlCommandBuilder(kundeTlfAdapter);
kundeTlfAdapter.SelectCommand = cmd1; // cmd1 is your SELECT command
kundeTlfAdapter.Update(kundeTlfDataSet, "Kunde_Tlf"); //I get eror here if I dont add the name of the table that needs Update "Kunde_Tlf"
}
catch (Exception err)
{
MessageBox.Show(err.Message.ToString());
}

Filling a DataTable in C# using MySQL

I'm attempting to fill a DataTable with results pulled from a MySQL database, however the DataTable, although it is initialised, doesn't populate. I wanted to use this DataTable to fill a ListView. Here's what I've got for the setting of the DataTable:
public DataTable SelectCharacters(string loginName)
{
this.Initialise();
string connection = "0.0.0.0";
string query = "SELECT * FROM characters WHERE _SteamName = '" + loginName + "'";
if (this.OpenConnection() == true)
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataAdapter returnVal = new MySqlDataAdapter(query,connection);
DataTable dt = new DataTable("CharacterInfo");
returnVal.Fill(dt);
this.CloseConnection();
return dt;
}
else
{
this.CloseConnection();
DataTable dt = new DataTable("CharacterInfo");
return dt;
}
}
And for the filling of the ListView, I've got:
private void button1_Click(object sender, EventArgs e)
{
string searchCriteria = textBox1.Text;
dt = characterDatabase.SelectCharacters(searchCriteria);
MessageBox.Show(dt.ToString());
listView1.View = View.Details;
ListViewItem iItem;
foreach (DataRow row in dt.Rows)
{
iItem = new ListViewItem();
for (int i = 0; i < row.ItemArray.Length; i++)
{
if (i == 0)
iItem.Text = row.ItemArray[i].ToString();
else
iItem.SubItems.Add(row.ItemArray[i].ToString());
}
listView1.Items.Add(iItem);
}
}
Is there something I'm missing? The MessageBox was included so I could see if it has populated, to no luck.
Thanks for any help you can give.
Check your connection string and instead of using
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataAdapter returnVal = new MySqlDataAdapter(query,connection);
DataTable dt = new DataTable("CharacterInfo");
returnVal.Fill(dt);
this.CloseConnection();
return dt;
you can use this one
MySqlCommand cmd = new MySqlCommand(query, connection);
DataTable dt = new DataTable();
dt.load(cmd.ExecuteReader());
return dt;
Well, I ... can't figure out what you have done here so I'll paste you my code with which I'm filling datagridview:
1) Connection should look something like this(if localhost is your server, else, IP adress of server machine):
string connection = #"server=localhost;uid=root;password=*******;database=*******;port=3306;charset=utf8";
2) Query is ok(it will return you something), but you shouldn't build SQL statements like that.. use parameters instead. See SQL injection.
3) Code:
void SelectAllFrom(string query, DataGridView dgv)
{
_dataTable.Clear();
try
{
_conn = new MySqlConnection(connection);
_conn.Open();
_cmd = new MySqlCommand
{
Connection = _conn,
CommandText = query
};
_cmd.ExecuteNonQuery();
_da = new MySqlDataAdapter(_cmd);
_da.Fill(_dataTable);
_cb = new MySqlCommandBuilder(_da);
dgv.DataSource = _dataTable;
dgv.DataMember = _dataTable.TableName;
dgv.AutoResizeColumns();
_conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (_conn != null) _conn.Close();
}
}
So, every time I want to display some content of table in mysql database I call this method, pass query string and datagridview name to that method. and, that is it.
For your sake, compare this example with your and see what can you use from both of it. Maybe, listview is not the best thing for you, just saying ...
hope that this will help you a little bit.
Debug your application and see if your sql statement/ connection string is correct and returns some value, also verify if your application is not throwing any exception.
Your connection string is invalid.
Set it as follows:
connection = "Server=myServer;Database=myDataBase;Uid=myUser;Pwd=myPassword;";
Refer: mysql connection strings
Here the following why the codes would not work.
Connection
The connection of your mySQL is invalid
Query
I guess do you want to search in the table, try this query
string query = "SELECT * FROM characters WHERE _SteamName LIKE '" + loginName + "%'";
notice the LIKE and % this could help to list all the data. for more details String Comparison Functions

Categories

Resources