I'm working on a project which uses an Access database. First of all I copy the information that i need from db and put it in a DataTable (with combining 2 tables). Over this datatable I search items; update, delete, add rows using a GridView and all of that happens in an ajax update panel.
Problem occurs when i try to apply the changes back to the db. What i want to do is get certain rows of the DataTable and update/insert/delete them to certain rows of certain tables. Important thing is database table has to contain the same information as the DataTable.
İ actually don't know if I can use the OledbDataAdapter.Update this way.
Here is the exeption that i get : Concurrency violation: the UpdateCommand affected 0 of the expected 1 records.
My Code:
void load_dtTable()
{
OleDbConnection bag = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=D:\\Profiles\\StjBugraO\\Desktop\\data.accdb");
DataTable dtResult = new DataTable();
if (Session["dtResult"] != null)
{
dtResult = (DataTable)Session["dtResult"];
}
else
{
bag.Open();
try
{
OleDbDataAdapter adtr = new OleDbDataAdapter("select gt.NodeID, gt.unit_num,gt.unit_name_text,gt2.ip_id ,gt2.server_name_text ,gt.call_flow_type From gt inner join gt2 on gt.cm_id=gt2.cm_id", bag);
dtResult.Clear();
adtr.Fill(dtResult);
adtr.Dispose();
dtResult.Columns[0].ColumnName = "NodeID";
dtResult.Columns[1].ColumnName = "Şube Kodu";
dtResult.Columns[2].ColumnName = "Şube ADI";
dtResult.Columns[3].ColumnName = "IP Adresi";
dtResult.Columns[4].ColumnName = "Call Manager";
dtResult.Columns[5].ColumnName = "Santral Tipi";
foreach (DataRow dr in dtResult.Rows)
{
if ((string)dr[5] == "P")
{
dr[5] = "PRI";
}
else if ((string)dr[5] == "A") dr[5] = "ANALOG";
}
}
catch (Exception e)
{
}
Session["dtResult"] = dtResult as DataTable;
bag.Close();
}
protected void Button3_Click(object sender, EventArgs e)
{
DataTable dtResult = Session["dtResult"] as DataTable;
//changing the names of the columns (that i need) to be the same with the db
dtResult.Columns[0].ColumnName = "NodeID";
dtResult.Columns[1].ColumnName = "unit_num";
dtResult.Columns[2].ColumnName = "unit_name_text";
dtResult.Columns[3].ColumnName = "ip_id";
dtResult.Columns[5].ColumnName = "call_flow_type";
OleDbConnection bag = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=D:\\Profiles\\StjBugraO\\Desktop\\data.accdb");
OleDbDataAdapter adtr2 = new OleDbDataAdapter("select NodeID ,unit_num ,unit_name_text , ip_id , call_flow_type from gt", bag);
OleDbCommandBuilder Ocmd = new OleDbCommandBuilder(adtr2);
adtr2.DeleteCommand=Ocmd.GetDeleteCommand();
adtr2.InsertCommand=Ocmd.GetInsertCommand();
adtr2.UpdateCommand=Ocmd.GetUpdateCommand();
DataTable dt = dtResult.GetChanges();
int updates = 0;
try
{
if(dt != null)
updates=adtr2.Update(dtResult);
}
catch (Exception ex)
{
Label1.Text = ex.Message.ToString();
}
//changing them back
dtResult.Columns[0].ColumnName = "NodeID";
dtResult.Columns[1].ColumnName = "Şube Kodu";
dtResult.Columns[2].ColumnName = "Şube ADI";
dtResult.Columns[3].ColumnName = "IP Adresi";
dtResult.Columns[4].ColumnName = "Call Manager";
dtResult.Columns[5].ColumnName = "Santral Tipi";
Label2.Text = updates + "changes applied.";
adtr2.Dispose();
bag.Close();
}
Related
I've got a dropdown whose values are retrieved from a database. I am retrieving ID and name from the database.
public void GetDepartment_temp()
{
try
{
DataTable dt = new DataTable();
listBoxDepartment.ClearSelection();
Get_Department objDAL = new Get_Department();
dt = objDAL.Get_Hospital_Department();
if (dt != null && dt.Rows.Count > 0)
{
foreach (DataRow row in dt.Rows)
{
listBoxDepartment.Items.Add(new ListItem(row["department_name"].ToString(), row["department_id"].ToString()));
}
}
}
catch (Exception) { }
}
I've got to show the number of employees of each department in the text box. Suppose a user selects human department, then the text box should display the number of employees in that department.
For the ListBox, only two values from the database can be retrieved. How can I show the number of employee in this condition?
public DataTable Get_Hospital_Department()
{
try
{
DataTable dt = new DataTable();
dt = DbAccessHelper.ExecuteDataSet("p_get_hospital_department", true).Tables[0];
return dt;
}
catch (Exception) { return null; }
}
CREATE PROCEDURE [dbo].[p_get_hospital_department]
AS
BEGIN
SET NOCOUNT ON;
SELECT department_id
,department_name
FROM [dbo].[tbl_hospital_department];
END
The statement For the ListBox, only two values from the database can be retrieved. is not correct. You can populate the datatable with as many fields as you want. However, you can set only the Value and text attributes of the Listbox item as you have done.
Change the stored procedure code to fetch the employee count also.
Mark your datatable dt as static and public.
Fetch the datable and you can play with the data as you want. You can fetch the employee count in the textbox on listview selected index changed as shown below:
public static DataTable dt = new DataTable();
public void GetDepartment_temp()
{
try
{
string connString = ConfigurationManager.ConnectionStrings["SOConnectionString"].ConnectionString;
SqlConnection connection = new SqlConnection(connString);
SqlCommand command =
new SqlCommand(
"select Department.DepartmentID, Department.[Department Name], count( Department.DepartmentID) as empCount from Department join Employee on Department.DepartmentID = Employee.DepartmentID group by Department.DepartmentID, Department.[Department Name]",
connection);
command.Connection.Open();
SqlDataAdapter da = new SqlDataAdapter(command);
da.Fill(dt);
dt.PrimaryKey = new DataColumn[] {dt.Columns["DepartmentID"]};
ListBox1.ClearSelection();
if (dt != null && dt.Rows.Count > 0)
{
foreach (DataRow row in dt.Rows)
{
ListBox1.Items.Add(new ListItem(row["Department Name"].ToString(),
row["DepartmentID"].ToString()));
}
}
}
catch (Exception ex)
{
}
}
protected void ListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
DataRow dr = dt.Rows.Find(Convert.ToInt32(ListBox1.SelectedItem.Value));
TextBox5.Text = dr["empCount"].ToString();
}
I have two datagridviews in one from. I need to get data from database to datagridview1 (using Select *from database...) then I want to add data from datagriwview to datagridview2 using Selected Rows.
First I wanted to solve this problem to get Selected Row's ID, when I select row in datagridview it shows in datagridview2, but when I select another row, it is updating in datagridview, it does not add as new row. I tried several ways but did not solve this problem, Is there anyone help me to solve this problem? Thanks
private void dataGridView1_CellDoubleClick_1(object sender, DataGridViewCellEventArgs e)
{
int id = Convert.ToInt32
(dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells["id"].Value);//3
try
{
MySqlConnection conn = new MySqlConnection(connection);
MySqlCommand command = start.CreateCommand();
command.CommandText = "SELECT id, muayine_adi, sabit_qiymet FROM tibbi_xidmetler WHERE id = '" + id.ToString() + "'";
conn.Open();
MySqlDataAdapter oxu = new MySqlDataAdapter(command);
DataTable dt = new DataTable();
oxu.Fill(dt);
dataGridView2.DataSource = dt;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Is quite simple the explanation: everytime that you make a double click to a datagridview1's cell you replace the old datatable with a new one. If you want append the result you can do something like this:
MySqlConnection conn = new MySqlConnection(connection);
MySqlCommand command = start.CreateCommand();
command.CommandText = "SELECT id, muayine_adi, sabit_qiymet FROM tibbi_xidmetler WHERE id = '" + id.ToString() + "'";
conn.Open();
MySqlDataAdapter oxu = new MySqlDataAdapter(command);
DataTable dt = new DataTable();
oxu.Fill(dt);
if(dataGridView2.DataSource != null) {
DataTable pr = dataGridView2.DataSource as DataTable;
pr.Merge(dt);
dataGridView2.DataSource = pr;
}
else
dataGridView2.DataSource = dt;
Since you have all information in datagridview1 you should just copy the contents of the selected row into a new row for datagridrow2.
The DataGridView is based on a DataSet which contains DataTables.
The DataTable contains rows.
You cannot move a row from one table to annother.
Instead you have to create a new row and insert into the DataTable of DataGridView2
private void dataGridView1_CellDoubleClick_1(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.CurrentRow.Cells["Id"].Value != null)
{
int Id = Convert.ToInt32(dataGridView1.CurrentRow.Cells["Id"].Value);
MySqlConnection start = new MySqlConnection(baglanti);
MySqlCommand command = start.CreateCommand();
command.CommandText = "SELECT id, muayine_adi, sabit_qiymet FROM tibbi_xidmetler WHERE id = '" + Id + "'";
start.Open();
MySqlDataAdapter oxu = new MySqlDataAdapter(command);
DataTable dt = new DataTable();
oxu.Fill(dt);
if (dt != null && dt.Rows.Count > 0)
{
int idx = dataGridView2.Rows.Count - 1;
dataGridView2.Rows.Add(dt.Rows.Count);
for (int i = 0; i <= dt.Rows.Count - 1; i++)
{
int rVal = (idx + i) + 1;
dataGridView2.Rows[rVal].Cells["id"].Value = dt.Rows[i]["id"].ToString();
dataGridView2.Rows[rVal].Cells["muayine_adi"].Value = dt.Rows[i]["muayine_adi"].ToString();
dataGridView2.Rows[rVal].Cells["sabit_qiymet"].Value = dt.Rows[i]["sabit_qiymet"].ToString();
}
}
start.Close();
}
}
How to get a specific column value from a DataTable in c#
I have a problem with my code C#.
I need read a specific column value from a DataTable.
I've tried using this solution without success, because the output is the name of column selected in the query (File) and not the value of field database.
I would greatly appreciate any help you can give me in working this problem.
Here is my code:
public DataTable GridViewBind()
{
using (OdbcConnection cn =
new OdbcConnection(ConfigurationManager.ConnectionStrings["cn"].ConnectionString))
{
sql1 = " SELECT FILE FROM tbl_A WHERE Id = 1; ";
using (OdbcDataAdapter command =
new OdbcDataAdapter(sql1, cn))
{
try
{
cn.Open();
dset = new DataSet();
dset.Clear();
command.Fill(dset);
DataTable dt = dset.Tables[0];
GridView1.DataSource = dt;
GridView1.DataBind();
Response.Write(dt.Columns[0].ToString());
return dt;
}
catch (Exception ex)
{
throw new ApplicationException("operation failed!", ex);
}
finally
{
if (command != null)
{
command.Dispose();
}
if (cn != null)
{
cn.Close();
cn.Dispose();
}
}
}
}
}
Edit #1
Now I have error:
System.IndexOutOfRangeException: There is no row at position 0.
public DataTable GridViewBind()
{
using (OdbcConnection cn =
new OdbcConnection(ConfigurationManager.ConnectionStrings["cn"].ConnectionString))
{
sql1 = " SELECT FILE FROM tbl_A WHERE Id = 1; ";
using (OdbcDataAdapter command =
new OdbcDataAdapter(sql1, cn))
{
try
{
cn.Open();
dset = new DataSet();
dset.Clear();
command.Fill(dset);
DataTable dt = dset.Tables[0];
GridView1.DataSource = dt;
GridView1.DataBind();
string file = dt.Rows[0].Field<string>(0);
Response.Write(file.ToString());
return dt;
}
catch (Exception ex)
{
throw new ApplicationException("operation failed!", ex);
}
finally
{
if (command != null)
{
command.Dispose();
}
if (cn != null)
{
cn.Close();
cn.Dispose();
}
}
}
}
}
The table normally contains multiple rows. Use a loop and use row.Field<string>(0) to access the value of each row.
foreach(DataRow row in dt.Rows)
{
string file = row.Field<string>("File");
}
You can also access it via index:
foreach(DataRow row in dt.Rows)
{
string file = row.Field<string>(0);
}
If you expect only one row, you can also use the indexer of DataRowCollection:
string file = dt.Rows[0].Field<string>(0);
Since this fails if the table is empty, use dt.Rows.Count to check if there is a row:
if(dt.Rows.Count > 0)
file = dt.Rows[0].Field<string>(0);
This is pretty simple to achieve. From the DataTable, first we can apply the Select function to get only the row that is associated with Id=1.
After that, we can do the CopyToDataTable() function so as to get it in the DataTable format.
Since, we are expecting that there is only row for Id=1, we can directly apply Rows[0] and then give the column name, convert to string and assign to file variable.
string file = dt.Select("Id=1").CopyToDataTable().Rows[0]["FILE"].ToString()
Note that if you are selecting string value, you need to apply single quotes. For eg, if Id is of string type, then you need to apply like below.
Id='1'
this is my code for multiple value in combobox. I have frmEntryHistory which entry a student id and his/her name in combobox , bookID and the title in combobox, and then date.
im using method on class library to get data from database and store them in dataset. And then i call that method on frmEntryHistory. I can appear ID-Tittle on combobox but not as record just name of columns on master_book table.
Please help me and sorry for confusing english. :)
// Method Library Class
public DataSet getBooks_ComboBox()
{
IDbDataAdapter adapter = null;
DataSet ds = null;
try
{
sb = new StringBuilder();
adapter = new MySqlDataAdapter();
comm = new MySqlCommand();
ds = new DataSet();
openConnection();
comm.Connection = conn;
sb.Append(#"select ID, ID + ' - ' + Title as Book from master_book");
comm.CommandText = sb.ToString();
adapter.SelectCommand = (MySqlCommand)comm;
adapter.Fill(ds);
closeConnection();
return ds;
}
catch (Exception ex)
{
return null;
}
}
//In my form Entry History
private void frmEntryHistory_Load(object sender, EventArgs e)
{
lblTgl.Text = DateTime.Now.ToString("dd/MM/yyyy");
Library lib = new Library();
DataSet ds = new DataSet();
//stored item into combobox
try
{
ds = lib.getBooks_ComboBox();
cmbBook.DataSource = ds.Tables[0];
cmbBook.DisplayMember = "Book";
cmbBook.ValueMember = "ID";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
what i want for output from combobox is ID - Title example : 1 - Novel asd, etc
After you fill the datatable, before you bind it to the combobox, you can create a new column to use. This example uses the pubs database:
DataSet1.titlesDataTable TitlesTable = new DataSet1.titlesDataTable();
titlesTableAdapter1.Fill(TitlesTable);
DataColumn DC = new DataColumn();
DC.ColumnName = "Test";
DC.DataType = typeof(string);
DC.Expression = string.Format("{0} + '-' + {1}", "title_id", "title");
TitlesTable.Columns.Add(DC);
comboBox1.DataSource = TitlesTable;
comboBox1.DisplayMember = "Test";
comboBox1.ValueMember = "title_id";
I have a gridview and Textboxes in Form1. When Form1 loads it will load the data into Gridview from database. I have a selectionChanged event of Gridview from where the data goes into textboxes and Now my problem is I want to edit them in Textboxes and save them to database, but When I click on save button it is creating a new record in the database and gridview. How to fix this ?
Below is my code for SaveButton:
private void btnSave_Click_1(object sender, EventArgs e)
{
DataRow dr = dt.NewRow();
da = new SqlDataAdapter("select * from Measurement", con);
SqlCommandBuilder cb = new SqlCommandBuilder(da);
dr["CellNumber"] = txtCellNo.Text.Trim();
dr["FirstName"] = txtFirstName.Text;
dr["LastName"] = txtLastName.Text;
dr["Shirt"] = txtShirt.Text;
dr["Pant"] = txtPant.Text;
dr["DueDate"] = txtDueDate.Text;
dr["Date"] = txtDate.Text;
if (dr["CellNumber"] == "")
{
MessageBox.Show("Please enter Cell Number");
}
else if (dr["CellNumber"] != "")
{
dr = dt.Select(" ID = " + txtID.Text)[0]; //updated here
}
try
{
da.Update(ds, "Measurement");
}
catch (DBConcurrencyException ex)
{
MessageBox.Show(ex.Message);
}
}
Code for Gridview:
private void dgv_SelectionChanged_1(object sender, EventArgs e)
{
if (dgv.SelectedRows.Count > 0)
{
foreach (DataGridViewRow row in dgv.SelectedRows)
{
//Send the first cell value into textbox'
txtLastName.Text = row.Cells["LastName"].Value.ToString();
txtFirstName.Text = row.Cells["FirstName"].Value.ToString();
txtCellNo.Text = row.Cells["CellNumber"].Value.ToString();
txtDate.Text = row.Cells["Date"].Value.ToString();
txtDueDate.Text = row.Cells["DueDate"].Value.ToString();
txtPant.Text = row.Cells["Pant"].Value.ToString();
txtShirt.Text = row.Cells["Shirt"].Value.ToString();
txtID.Text = row.Cells["ID"].Value.ToString();
}
}
}
da.Update(ds, "Measurement"); is inserting a new record because the RowState property of the row you are attempting to update is set to Added since you are assigning the cell values to a new row. You need to update the values of an existing row. Check DbDataAdapter.Update Documentation :
When an application calls the Update method, the DbDataAdapter
examines the RowState property, and executes the required INSERT,
UPDATE, or DELETE statements iteratively for each row, based on the
order of the indexes configured in the DataSet
Try this :
private void btnSave_Click_1(object sender, EventArgs e)
{
da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand("select * from Measurement where ID = #ID",con);
da.SelectCommand.Parameters.AddWithValue("#ID",int.Parse(txtID.Text));
SqlCommandBuilder cb = new SqlCommandBuilder(da);
da.Fill(ds, "Measurement");
if (String.IsNullOrEmpty(txtCellNo.Text.Trim()))
{
MessageBox.Show("Please enter Cell Number");
}
else
{
try
{
dr = ds.Tables["Measurement"].Rows[0];
dr["CellNumber"] = txtCellNo.Text.Trim();
dr["FirstName"] = txtFirstName.Text;
dr["LastName"] = txtLastName.Text;
dr["Shirt"] = txtShirt.Text;
dr["Pant"] = txtPant.Text;
dr["DueDate"] = txtDueDate.Text;
dr["Date"] = txtDate.Text;
cb.GetUpdateCommand();
da.Update(ds, "Measurement");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Your missing the WHERE condition in your query
da = new SqlDataAdapter("select * from Measurement WHERE ID = " + txtID.Text, con);
What you should look at is the way you save into the db.
What is happening now is you are inserting a new entity/row in the db instead of updating the one you already loaded.
You are missing the primary key field. The ID. So it will always be a new entity to add not one that exists and needs updating.
da = new SqlDataAdapter("select * from Measurement", con);
SqlCommandBuilder cb = new SqlCommandBuilder(da);
dr = dt.Select(" ID = " + txtID.Text)[0];
if (txtCellNo.Text == "")
{
MessageBox.Show("Please enter Cell Number");
}
else if (dr["CellNumber"] != "")
{
dr["CellNumber"] = txtCellNo.Text.Trim();
dr["FirstName"] = txtFirstName.Text;
dr["LastName"] = txtLastName.Text;
dr["Shirt"] = txtShirt.Text;
dr["Pant"] = txtPant.Text;
dr["DueDate"] = txtDueDate.Text;
dr["Date"] = txtDate.Text;
}
try
{
da.Update(ds, "Measurement");
}
catch (DBConcurrencyException ex)
{
MessageBox.Show(ex.Message);
}