Updating Database From Data Grid View Modified Rows c# - c#

I am working in C#. I have a windows form with a data grid view that lists items for the user to review. The data source for the data grid view is a data table
public DataTable GetSFNoDFInventory()
{
// DECLARATIONS
using (DataTable toReturn = new DataTable())
{
//string updateProcName;
//SqlCommand cmdUpdate;
// Create and prepare a command object to be used for the SELECT statement of the data adapter.
using (SqlCommand cmdSelect = new SqlCommand
{
Connection = new SqlConnection(ConString),
CommandType = CommandType.StoredProcedure,
CommandText = "usr.uspSFNoDFGetInventoryReview"
})
{
using (SqlDataAdapter da = new SqlDataAdapter(cmdSelect))
{
da.Fill(toReturn);
}
}
return toReturn;
}
}
The rows in the data grid view have two check boxes for the user to select to update the row. One check box drops the row from further processing. The other flags the record to be included in an email message. I'm trying to collect the updated rows to update the SQL database table using a data view and SQL data adapter.
private void btnSaveDropsAndEmails_Click(object sender, EventArgs e)
{
DataView vwDropSCCF = new DataView(Shared.DtReviewClaims.DefaultView.ToTable("drpSCCF"), "DropRcd = 1", "", DataViewRowState.ModifiedCurrent);
if (dgReviewClaims.EndEdit())
{
Shared.SqlWrapper.UpdateDropEmail(vwDropSCCF);
}
}
However, the count property for vwDropSCCF is zero (0). What am I doing wrong?

Related

C# Not updating modified dataset to SQL Server table

I've been working on a small project and came to an issue with a SQL Server database. The SQL Server database works fine when connecting and reading from it. There are no issues when it comes to the variables, they all update fine.
However, the database itself does not update at all. I believe it is the da.Update that is going wrong, but I've never worked with SQL before so I can't find what is wrong with it.
What it should do:
Read data from the SQL Server table
Put it in a DataTable
Take changes from a list and put them into the DataTable
Add the changes to the database
What it does do:
Reads the data from the SQL Server table
Puts it in a DataTable
Takes changes from a list and puts them into the DataTable
Doesn't update the database, but does not fail the try and catch
Code:
public void PushToDatabase()
{
// Get update from list
PropertiesList[0] = Name;
PropertiesList[1] = Token;
PropertiesList[2] = ClientID;
PropertiesList[3] = ClientInfo;
PropertiesList[4] = Owner;
PropertiesList[5] = OtherID;
PropertiesList[6] = Prefix;
PropertiesList[7] = ApiKey;
// Connect to the database
using (var connection = new SqlConnection(connectionString))
using (SqlDataAdapter da = new SqlDataAdapter("SELECT ID, Name, Token, ClientID, ClientInfo, Owner, OtherID, Prefix, GoogleApi FROM dt", connection))
{
SqlCommandBuilder cb = new SqlCommandBuilder(da);
connection.Open();
DataTable dt = new DataTable();
// Load then modify the data
da.Fill(dt);
dt.Rows[0].BeginEdit();
dt.Rows[0][1] = PropertiesList[0];
dt.Rows[0][2] = PropertiesList[1];
dt.Rows[0][3] = PropertiesList[2];
dt.Rows[0][4] = PropertiesList[3];
dt.Rows[0][5] = PropertiesList[4];
dt.Rows[0][6] = PropertiesList[5];
dt.Rows[0][7] = PropertiesList[6];
dt.Rows[0][8] = PropertiesList[7];
dt.Rows[0].EndEdit();
// Put the data back
try
{
da.AcceptChangesDuringUpdate = true;
da.DeleteCommand = cb.GetDeleteCommand(true);
da.UpdateCommand = cb.GetUpdateCommand(true);
da.InsertCommand = cb.GetInsertCommand(true);
dt.AcceptChanges();
da.Update(dt);
MessageBox.Show("Properties Updated", "Update"); //this completes fine and displays the updated message
}
catch
{
MessageBox.Show("Cant Store data", "Error");
}
connection.Close();
}
}
Sorry about the messy code I've been adding things in to try to fix this but I have not had any success.
You shouldn't be calling AcceptChanges before the Update, so you need to remove dt.AcceptChanges();
A longer answer is that the AcceptChanges will mark all the added and updated rows as now being unmodified, and it will permanently delete the rows you've asked to be deleted (from the datatable -- not the table in Sql Server). Then when you call Update, it scans the databable looking for any rows that are in "Added", "Modified" or "Deleted" status, and finds there are none (because you just changed them all to "Unmodified" via AcceptChanges), so nothing is sent to the database.

asp.net c# dropdown list findbytext keeps adding item?

May be a noob question. But I am scratching my head what I am doing wrong here.
protected void ddlClientNum_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(Bussiness.GetConnectionString("Default")))
{
try
{
SqlDataAdapter adapter = new SqlDataAdapter("select distinct client_name from [dbo].[customer_master] where client_number=" + ddlClientNum.SelectedItem.Text + " order by client_name", con);
adapter.Fill(dt);
ddlClientName.DataSource = dt;
ddlClientName.DataTextField = "client_name";
ddlClientName.DataValueField = "client_name";
ddlClientName.DataBind();
ddlClientName.ClearSelection();
//ddlClientName.SelectedValue = ddlClientName.Items.FindByText((ddlClientNum.SelectedItem.Text).ToString()).Value;
//ddlClientName.SelectedValue = ddlClientName.Items.FindByText((dt.Rows[0][0]).ToString()).Value;
//ddlClientName.Items.FindByText((dt.Rows[0][0]).ToString()).Selected = true;
ddlClientName.SelectedIndex = ddlClientName.Items.IndexOf(ddlClientName.Items.FindByText((dt.Rows[0][0]).ToString()));
}
}
}
I am populating client number and client name dropdownlist on page load. On selection of client number I need to select the respective client name but I don't want to Clear the Items. I need users to be able to see the other client names but need to Select the Client name for selected client Number. I Have tried the 3 things but it keeps adding the selected client name.
So, selected client name is occurring as many times I select the respective Client Number and stays there even if I select another client Number.
e.g. I select Client Number :176 | Client Name shows "XYZ Client" selected but occurs twice in the list. If I select any other client number and then again select 176 I can see "XYZ Client" occuring in the list thrice.
Blues and yellows are the repeating ones.
Then you don't need to bind again here. just set the selected index.
Also, I suggest you to use Parameterized queries. Otherwise, It will be vulnerable to SQL injection.
For more info : https://www.mssqltips.com/sqlservertip/2981/using-parameters-for-sql-server-queries-and-stored-procedures/
protected void ddlClientNum_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dt = new DataTable();
using (SqlConnection con = new SqlConnection(Bussiness.GetConnectionString("Default")))
{
try
{
SqlDataAdapter adapter = new SqlDataAdapter("select distinct client_name from [dbo].[customer_master] where client_number=" + ddlClientNum.SelectedItem.Text + " order by client_name", con);
adapter.Fill(dt);
ddlClientName.ClearSelection();
ddlClientName.SelectedIndex = ddlClientName.Items.IndexOf(ddlClientName.Items.FindByText((dt.Rows[0][0]).ToString()));
}
}
}

Moving Data from DataSet to Oracle Database using C#

I've been squeezing my mind trying to figure out why my code isn't working.
I am trying to read from a DataSet that filled with data from access database and insert the data into an Oracle database which is created previously.
When I try the following code it won't work and although I use the try and catch block, when debugging it would freeze and won't show me any error.
if can see that I have commented out the block just right above my foreach loop..which works perfectly, Any help from you is so much appreciated :
private void button3_Click(object sender, EventArgs e)
{
string query1 = "Select * from Test;";
string StrQuery= "Insert Into TEST (ID, DATA) Values (:ID, :DATA)";
Conn = new OleDbConnection(connStr);
Conn.Open();
using (OleDbConnection connection1 = new OleDbConnection(connStr))
{
using (OleDbDataAdapter adapter1 = new OleDbDataAdapter(query1, connection1))
{
DataSet ds1 = new DataSet();
adapter1.Fill(ds1);
// no need for refilling DataGridView1.DataSource = ds.Tables[0]
// insterting the dataset into oracle
try
{
using (OracleConnection connect = new OracleConnection(oradb1))
{
connect.Open();
using (OracleCommand comma = new OracleCommand(StrQuery, connect))
{
/*comma.Parameters.Add(new OracleParameter(":ID", 2));
comma.Parameters.Add(new OracleParameter(":DATA", 2));
comma.ExecuteNonQuery();*/
foreach (DataRow drRow in ds1.Tables[0].Rows)
{
for (int i = 0; i < ds1.Tables[0].Columns.Count; i++)
{
comma.Parameters.Add(new OracleParameter(":ID", drRow[i]));
comma.Parameters.Add(new OracleParameter(":DATA", drRow[i]));
comma.ExecuteNonQuery();
}
}
connect.Close();
connect.Dispose();
}
}
}
catch (OracleException)
{
System.Diagnostics.Debugger.Break();
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Conn.Close();
}
You are looping columns but adding the drRow[i] as values in the parameters.
I do not think this is what you intended.
skip the columns loop and add the first column value to id and second column value to data.
that should be what you wanted.... if not then describe a bit more...
Expanding on Judgemaik's answer, I believe you need to do something like this instead (can't really tell what the names of the columns in your access table are but you get the idea:
foreach (DataRow drRow in ds1.Tables[0].Rows)
{
comma.Parameters.Add(new OracleParameter(":ID", drRow["IDColumnFromAccessDB"]));
comma.Parameters.Add(new OracleParameter(":DATA", drRow["DATAColumnFromAccessDB"]));
comma.ExecuteNonQuery();
}
A similar approach is outlined in my answer here. In that particular case I was moving data from SQL Server Compact into Access, but the same idea could very well be used to move data between any two OleDb data sources.
It uses an OleDbDataAdapter to pull the source table into a DataTable, copies it over to another DataTable, and then uses another OleDbDataAdapter to update the corresponding table in the destination database.

Retrieve/insert data using SQLiteDataAdapter

I'm currently creating a small application using Windows Forms and SQLite. After reading some tutorials I implemented this method for data retrieval:
public DataTable GetDataTable(ref SQLiteDataAdapter adapter, string sql)
{
DataTable dt = new DataTable();
// Connect to database.
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
// Create database adapter using specified query
using (adapter = new SQLiteDataAdapter(sql, connection))
// Create command builder to generate SQL update, insert and delete commands
using (SQLiteCommandBuilder command = new SQLiteCommandBuilder(adapter))
{
// Populate datatable to return, using the database adapter
adapter.Fill(dt);
}
return dt;
}
(As well as another GetDataTable which doesn't take an SQLiteDataAdapter as parameter)
I have three classes, let's call them UI, Link and Database. The UI does nothing but displaying the data and raising events upon user interaction. The Link creates the Database and a SQLiteDataAdapter, retrieves a data table through the method mentioned above, and binds it to a data grid view on the UI. The user cannot alter the table through the data grid view, but should do so through some text boxes. (does this make binding the table to the dgv obosolete?)
What's the best way to get the user input from the text boxes to the database, using the adapter? Or should I use DataReader and some Insert method instead of an adapter?
As of know, the UI exposes its controls through Get-methods. Is there a better solution?
private void Initialize()
{
// Subscribe to userInterface events
userInterface.DataGridViewSelectionChanged += new EventHandler(userInterface_DataGridViewSelectionChanged);
userInterface.NewClicked += new EventHandler(userInterface_NewClicked);
userInterface.SaveClicked += new EventHandler(userInterface_SaveClicked);
// Get dataGridView from userInterface and bind to database
bindingSource = new BindingSource();
bindingSource.DataSource = database.GetDataTable(ref adapter, "SELECT * FROM SomeTable");
userInterface.GetDataGridView().DataSource = bindingSource;
}
void userInterface_DataGridViewSelectionChanged(object sender, EventArgs e)
{
if (userInterface.GetDataGridView().SelectedRows.Count != 0)
{
DataGridViewRow row = userInterface.GetDataGridView().SelectedRows[0];
userInterface.GetIDTextBox().Text = row.Cells["PrimaryKey].Value.ToString();
userInterface.GetOtherIDTextBox().Text = row.Cells["ForeignKey"].Value.ToString();
DataTable dt = database.GetDataTable("SELECT * from SomeTable WHERE ForeignKey=" + row.Cells["ForeignKey"].Value);
userInterface.GetLastNameTextBox().Text = dt.Rows[0]["LastName"].ToString();
userInterface.GetFirstNameTextBox().Text = dt.Rows[0]["FirstName"].ToString();
userInterface.GetCompanyTextBox().Text = dt.Rows[0]["Company"].ToString();
}
}
void userInterface_NewClicked(object sender, EventArgs e)
{
// Get all text boxes and clear them
// Let the UI take care of this by itself?
}
void userInterface_SaveClicked(object sender, EventArgs e)
{
// Get text/data from all text boxes and insert (or update if editing table) into database
// adapter.Update(...)?
}
Cheers!
INSERT, UPDATE and DELETE operations are the working of a DbCommand. You need a different method that takes the sql string and a collection of SQLiteParameter that you use for the INSERT.
I will try to write some pseudocode for the INSERT operation
public class MyHelperClass
{
public static int InsertCommand(string sql, SQLiteParameter[] parameters)
{
int result = 0;
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
using (SQLiteCommand cmd = new SQLiteCommand(sql, connection))
{
cmd.Parameters.AddRange(parameters);
result = cmd.ExecuteNonQuery();
}
return result;
}
}
Now you have to build the parameter array to pass to the help method and this should be done from your UI code
string sqlCommand = "INSERT INTO table1 (FirstName, LastName) VALUES (#fName, #lName)";
SQLiteParameter[] p = new SQLiteParameter[2];
p[0] = new SQLiteParameter("#fName", TextBox1.Text);
p[1] = new SQLiteParameter("#lName", TextBox2.Text);
int rowAdded = MyHelperClass,InsertCommand(sql, p);
The operation for the UPDATE and DELETE command are similar. Also I suggest you to add a version of your GetDataTable that accepts a parameter array instead of building sql commands with string concatenation. As repetead innumerable times here string concatenation leads to errors and, worst of all, to weak code easily exposed to sql injection.

how to validate fields from DB before binding the data to the details view

how to validate fields from DB before binding them to details view
I have some fields which needs to be validated before going into the details view
For Eg null valued fields should be eleminated ... and need to get some more data for the
fields which are foreign keys in this table (ie have the data in other table )
i thought i can do this in ondatabinding event ...
protected void dvDataBinding(object sender, EventArgs e)
{
}
in the following function i will pass the req_ID..
data binding in details view ...
public DataSet GetExceptionDataDetailedView(string strWorkRequestID)
{
DBManager objDBManager = new DBManager();
StringBuilder strSQL = new StringBuilder();
StringBuilder strColName = new StringBuilder(); //string strTableField;
DataSet objDataSet;
try
{
strSQL.Append("SELECT * FROM work_request where work_request_id='");
strSQL.Append(strWorkRequestID);
strSQL.Append("'");
// Open the connection object
objConnection = objDBManager.OpenDBConnection();
//Create a command object to execute the Store procedure
objCommand = new MySqlCommand();
objCommand.CommandText = strSQL.ToString();
objCommand.CommandType = CommandType.Text;
objCommand.Connection = objConnection;
MySqlDataAdapter objDataAdapter = new MySqlDataAdapter(objCommand);
objDataSet = new DataSet();
objDataSet.Tables.Clear();
objDataAdapter.Fill(objDataSet);
}
catch (MySqlException exSQL)
{
throw exSQL;
}
catch (Exception exGeneral)
{
throw exGeneral;
}
finally
{
//close the connection object
objDBManager.CloseDBConnection();
}
return objDataSet;
}
Thanks in advance
Why do you wish to remove data wen you are binding, why not remove the data from the dataset before it is returned by GetExceptionDataDetailedView. That way you don't ave to worry about the details view as it will only bind to the correct data. also why would you want to lookup foreign keys, the correct way would be to create a join in your sql statement to the foreign table and use the relevent field from the foreign table.

Categories

Resources