SQL Command Builder Query values - c#

I have a SQLDataAdapter, in my query i am fetching two fields, ID(PK), Name.
I registered a sql command builder to my data adapter so i don't have to write queries to update table in database.
when I call the da.update() method, sql throws error that cannot insert null into DimensionID, due to this error, i have to select this field too in my dataset, and then i filled this field in grid with appropriate value. then da.update() worked.
Now the problem is that I don't want this field to appear in my gird, when i set its visible property to false, command builder omits this column in query. To cater this issue I have to set the column width to 0, but there is still a tiny line in my grid.
Is there a better way to handle this situation ? except that I manually write queries.
Below is Code to Populate Grid;
private void frmAttributes_Load(object sender, EventArgs e)
{
ds.Tables.Add("Attributes");
SqlCommand cmd = new SqlCommand();
cmd.Connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
cmd.CommandText = "select ID,Attribute,Code,DimensionID from DimensionAttribute where dimensionid = " + SelectedAttribute;
da.SelectCommand = cmd;
cb.DataAdapter = da;
da.Fill(ds,"Attributes");
this.dgvAttributes.DataSource = ds.Tables["Attributes"];
this.dgvAttributes.Columns["ID"].Visible = false;
this.dgvAttributes.Columns["DimensionID"].Width = 0;
}
and here is the code behind Updated Button:
private void btnOk_Click(object sender, EventArgs e)
{
if (ds.HasChanges())
{
DialogResult d = new DialogResult();
d = MessageBox.Show("Are you sure you want to save changes to database?", this.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (d == DialogResult.Yes)
{
try
{
fillDimensionID();
da.UpdateCommand = cb.GetUpdateCommand();
da.InsertCommand = cb.GetInsertCommand();
da.DeleteCommand = cb.GetDeleteCommand();
da.Update(ds,"Attributes");
this.DialogResult = DialogResult.OK;
this.Close();
}
catch (Exception)
{
throw;
}
}
else
{
return;
}
}
}

This is a problem with AutoGeneratedCommands. They require every attribute assigned a proper value before update is triggered.
You can adopt either of the following:
Modify the column DimensionID to accept null values; or
Write your own update SP in the database and register it as UpdateCommand with your data adapter.
hope this will show you the path.

Related

C# Clear/Reset Listbox populated with Datasource

I have some methods that lists a variety of details in multiple Listboxes that can be added to a client, e.g. different crimes. The method below selects all the crimes from the CriminalRecord table where the ClientId = selected client's id and then populates the listCriminalRecord listbox with this data.
private void PopulateCriminalRecord()
{
string query = "SELECT * FROM CriminalRecord " +
"a INNER JOIN ClientCriminalRecord b ON a.Id = b.CriminalRecordId " +
"WHERE b.ClientId = #ClientId ORDER BY Crime ASC";
using (connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
command.Parameters.AddWithValue("#ClientId", newId);
DataTable dTable = new DataTable();
adapter.Fill(dTable);
listCriminalRecord.DisplayMember = "Crime";
listCriminalRecord.ValueMember = "Id";
listCriminalRecord.DataSource = dTable;
}
}
When the user is finished with entering the client's details, they will click a button, be prompted with a message etc etc.
private void btnFinish_Click(object sender, EventArgs e)
{
DialogResult result = MessageBox.Show("Are you sure you've finished & filled in all of the Client's details?", "Save and exit", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
DisableStep2();
EnableStep1();
}
}
The EnableStep1(); method just enables and clears some textboxes and the DisableStep2(); method does the same but disables some textboxes. After this, I want all of the listboxes to be reset/cleared. I've tried listCriminalRecord.Items.Clear() but it expresses an error. I'm unsure on how to do this.
Any help would be fantastic.
Try this:
listCriminalRecord.DataSource = null;

Update DataGridView Checked Record to the Database

So I have this DataGridView on which there are two columns which I am retrieving from my SQL Server database. Now, in the second column, we have a bit field which shows as a CheckBox in my Windows Application designer. So, I want to, on CellContentClick event be able to update the value that just got deselected into my database. But seems like I am going nowhere.
Here is my code below:
private void gvTurnOffNotifications_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
foreach (DataGridViewRow row in gvTurnOffNotifications.Rows)
{
DataGridViewCheckBoxCell cell = row.Cells[1] as DataGridViewCheckBoxCell;
//We don't want a null exception!
if (cell.Value != null)
{
bool result = Convert.ToBoolean(row.Cells[1].Value);
if (result == true)
{
//It's checked!
btnUpdateTurnOff.Enabled = true;
myConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
using (mySQLConnection = new SqlConnection(myConnectionString))
{
int temp = 1;
bool change = false;
string procedureName = "update UsersNotified Set AllowNotification='" + change + "' where AllowNotification='" + false+ "'";
mySQLCommand = new SqlCommand(procedureName, mySQLConnection);
mySQLCommand.CommandType = CommandType.Text;
mySQLCommand.Connection = mySQLConnection;
mySQLCommand.Connection.Open();
mySQLCommand.ExecuteNonQuery();
}
}
}
}
}
And then when I click on my "Update" button, I want to send the updated griddata for storing in my database as below:
private void btnUpdateTurnOff_Click(object sender, EventArgs e)
{
myConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
using (mySQLConnection = new SqlConnection(myConnectionString))
{
mySQLDataAdapter = new SqlDataAdapter("spGetAllUpdatedNotifications", mySQLConnection);
mySQLDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
mySQLCommand.Connection = mySQLConnection;
mySQLCommand.Connection.Open();
DataSet ds = new DataSet();
mySQLDataAdapter.Fill(ds);
mySQLDataAdapter.UpdateCommand = mySQLCommand;
mySQLDataAdapter.Update(ds);
}
}
The spGetAllUpdatedNotifications object in my Update block is a stored procedure I am calling just to retrieve the records from the database so I can update them on the fly in my DataSet. Here is the definition below:
create proc spGetAllUpdatedNotifications
as
begin
SELECT UserName, AllowNotification FROM UsersNotified where AllowNotification=1
end
GO
For more context: When my form loads, I am selecting all the records from the database which have their AllowNotification field set to bit 1 (true in C#) and once a user unticks a specific user (in other words, that user would not be allowed to receive notifications anymore) and once I click on the Update button, it should set the property to false (bit 0 in the database).
Instead of updating the one record which I have deselected, it updates all of them. "All" in this case are the records which have AllowNotification=1. I only want to set AllowNotification=0 for the deselected/unchecked record only
Any suggestions on how I can go about achieving this?
I am not sure what logic makes you to loop thru all the rows of the DataGridView just to update one row in the database.
If you want to update AllowNotification value for the username for which checkbox is checked or unchecked the logic would be this.
Figure out the updated value of the checkbox which is clicked in the gridview.
Store the updated value (True or False) in a boolean variable.
Retrieve the corresponding username of from the other cell of the same row the gridview.
Execute update query with criteria "WHERE UserName = {userName}".
You need to write CellContentClick event of the DataGridView as following.
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 1) //Assuming Checkbox is displayed in 2nd column.
{
this.dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
var result = this.dataGridView1[e.ColumnIndex, e.RowIndex].Value;
var userName = this.dataGridView1[0, e.RowIndex].Value; //Assumin username is displayed in fist column
var connectionString = "Your Connection String";
//Set value of your own connection string above.
var sqlQuery = "UPDATE UsersNotified SET AllowNotification = #allowNotification WHERE UserName = #userName";
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(sqlQuery, connection))
{
command.CommandType = CommandType.Text;
command.Parameters.Add("#allowNotification", SqlDbType.Bit).Value = result;
command.Parameters.Add("#UserName", SqlDbType.NVarChar).Value = userName;
connection.Open();
command.ExecuteNonQuery();
}
}
}
}
This should help you resolve your issue.
I have a partial solution (It doesn't work a 100% but at least its a step in the right direction):
private void gvTurnOffNotifications_SelectionChanged(object sender, EventArgs e)
{
if (gvTurnOffNotifications.SelectedCells.Count > 0)
{
int selectedrowindex = gvTurnOffNotifications.SelectedCells[0].RowIndex;
DataGridViewRow selectedRow = gvTurnOffNotifications.Rows[selectedrowindex];
getUserSelected = Convert.ToString(selectedRow.Cells["UserName"].Value);
MessageBox.Show(getUserSelected);
foreach (DataGridViewRow row in gvTurnOffNotifications.Rows)
{
DataGridViewCheckBoxCell cell = row.Cells[1] as DataGridViewCheckBoxCell;
//We don't want a null exception!
if (cell.Value != null)
{
//It's checked!
btnUpdateTurnOff.Enabled = true;
myConnectionString = ConfigurationManager.ConnectionStrings["FSK_ServiceMonitor_Users_Management.Properties.Settings.FSK_ServiceMonitorConnectionString"].ConnectionString;
using (mySQLConnection = new SqlConnection(myConnectionString))
{
bool change = false;
string procedureName = "update UsersNotified Set AllowNotification='" + change + "' where UserName='" + getUserSelected + "'";
//MessageBox.Show(cell.Value.ToString());
mySQLCommand = new SqlCommand(procedureName, mySQLConnection);
mySQLCommand.CommandType = CommandType.Text;
mySQLCommand.Connection = mySQLConnection;
mySQLCommand.Connection.Open();
mySQLCommand.ExecuteNonQuery();
}
}
}
}
}
Problem is that it just takes the first row without me having selected the row I want to deselect.

Insert DataGridView values into MySql database. c#

I want to add new values to MySql database from dataGridView1. The code itself appears to be correct, no errors in Visual Studio 2012, but there is no data inserted in my db.
Here's the code I'm using:
private void button2_Click(object sender, EventArgs e)
{
confirm exec = new confirm();
}
public class confirm
{
public void method(DataGridViewCellEventArgs f)
{
DataGridView dataGridView1 = new DataGridView();
Label label1 = new Label(); // contains User ID which is used for payer_code
Label label6 = new Label(); // contains current dayTime
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if ((bool)dataGridView1.Rows[f.RowIndex].Cells["paidDataGridViewTextBoxColumn"].Value == true)
{
try
{
string MyConnectionString = "Server=localhost; Database=contractsdb; Uid=root; Pwd=";
MySqlConnection connection = new MySqlConnection(MyConnectionString);
MySqlCommand cmd = new MySqlCommand();
cmd = connection.CreateCommand();
connection.Open();
cmd.CommandText = "INSERT INTO payments(pay_name, pay_code, payer_code, pay_sum, pay_date)VALUES(#pay_name, #pay_code, #payer_code, #pay_sum, #pay_date)";
cmd.Parameters.AddWithValue("#pay_name", dataGridView1.Rows[f.RowIndex].Cells["contractnameDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#pay_code", dataGridView1.Rows[f.RowIndex].Cells["contractcodeDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#payer_code", label1.Text);
cmd.Parameters.AddWithValue("#pay_sum", dataGridView1.Rows[f.RowIndex].Cells["sumDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#pay_date", label6.Text);
cmd.ExecuteNonQuery();
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}
I think you are misunderstanding something about OOP. Do it like this:
your confirm class method should also have the reference of datagridview1 (you are creating an empty datagridview so it never goes even into the foreach loop)
public void method(DataGridView datagridview1) //remove your first argument, you don't need it anymore
{
//delete the line "DataGridView dataGridView1 = new DataGridView();"
//and keep the rest of the code as it is
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if(row.Cells["paidDataGridViewTextBoxColumn"].Value == true) //it will check every row, and you don't need "DataGridViewCellEventArgs" argument now
{
try
{
//your code, it will be same here
}
}
}
for calling the method:
(use the same button_click event as you were doing)
private void button2_Click(object sender, EventArgs e)
{
confirm exec = new confirm();
exec.method(datagridview1); //pass "datagridview1" reference
}
It will pass the reference of your original datagridview1 to the confirm class.

how do you execute a sql command on a button click and then have it populate a dataset?

Ok I have a SQL query that I need to run on a button click and then output to a dataset.
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
Assembly.GetExecutingAssembly().GetName().Version.ToString();
var line = txtLine.Text;
var serial = txtSerial.Text;
var station = txtStation.Text;
}
private void btnGo_Click(object sender, EventArgs e)
{
var line = txtLine.Text;
var serial = txtSerial.Text;
var station = txtStation.Text;
if (txtLine.Text.Trim().Length == 0)
{
MessageBox.Show("Please enter a Line");
}
else if (txtSerial.Text.Trim().Length == 0)
{
MessageBox.Show("Please enter a Serial");
}
else if (txtStation.Text.Trim().Length == 0)
{
MessageBox.Show("Please enter a Station");
}
else
{
//SQL command goes here.
}
}
}
I have the SQL command I just need to know how to execute it as a non store procedure and output the data to the dataGridView1 object.
You have not provided enough informations to show you more than pseudo code. However, use the using statement to ensure that everything implementing IDisposable gets disposed properly and the connection gets closed (even on error).
Use sql-parameters to avoid sql injection and conversion/localization issues.
string sql = "SELECT Columns FROM dbo.TableName WHERE Column=#ParamName";
using (var con = new SqlConnection("Connection String Here"))
using (var da = new SqlDataAdapter(sql, con))
{
da.SelectCommand.Parameters.AddWithValue("#ParamName", "Param Value");
// other parameters
DataTable table = new DataTable();
da.Fill(table);
dataGridView1.DataSource = table;
}

ORA-00904 : invalid identifier error when updating

My Global Class :
class Global
{
public static OleDbDataAdapter adapter;
public static DataTable dt;
}
The procedure I'm using to fill my DataGridView :
OleDbConnection connection;
OleDbCommandBuilder builder;
void gridfill()
{
connection = new OleDbConnection("Provider=MSDAORA;Data Source=XXX;"
+ "user id=XXX;password=XXX;"
+ "persist security info=false;");
Global.adapter = new OleDbDataAdapter("select \"Id\", \"UserComputer\", \"GuralID\", \"Type\", \"CreatedOn\", \"State\" from COMPUTERS", connection);
builder = new OleDbCommandBuilder(Global.adapter);
Global.dt = new DataTable();
Global.adapter.Fill(Global.dt);
dataGridView1.DataSource = Global.dt;
dataGridView1.ReadOnly = true;
}
The procedure I'm using to update a field in a row in my Oracle DB :
private void button1_Click(object sender, EventArgs e)
{
try
{
if (comboBox1.Text == "New")
{
Global.dt.Rows[rowId]["State"] = 0;
}
else if (comboBox1.Text == "Old")
{
Global.dt.Rows[rowId]["State"] = 1;
}
else if (comboBox1.Text == "Junk")
{
Global.dt.Rows[rowId]["State"] = 2;
}
Global.adapter.Update(Global.dt);
this.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
When I run, I get my DataGridView filled. That part is okay. And then I double click on a row and another form shows up. That form gets values of the selected row. There's an update button on it. I use it to change the value of a field of the selected row. 3rd code I shared with you is the one to do that. But I get ORA-00904: "STATE" invalid identifier.
I debugged it. The error comes in this line :
Global.adapter.Update(Global.dt);
TIPS:
Tables are actually created by ORM classes.
As I know this is something about double quotes.
Ex : 'Select State from COMPUTERS' does not work but 'Select "State" from COMPUTERS' does.
I used '\' prefix in my SQL query after having the same issue when filling DataGridView. The problem solved.
But I cannot use it when trying to assign a new value to the field. And I need a way to do that.
I guess the problem is here :
Global.dt.Rows[rowId]["State"] = 0;
What can I do? Thanks.
Try setting the QuotePrefix and QuoteSuffix on your OleDbCommandBuilder object to ".
By default, the OleDbCommandBuilder doesn't know what quotation system the database system it's talking to uses.

Categories