I have a button which saves the contents edited in datagridview in my UI design. Here is the code for that Button_Save:
public void btnUpdate_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
System.Data.SqlClient.SqlConnection sqlConnection1 =
new System.Data.SqlClient.SqlConnection("server=Test; Integrated Security=true; Database=Test;");
System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
var sql = new StringBuilder();
sql.AppendLine("UPDATE dbo.JobStatus");
sql.AppendLine("Set ShipTrackingNumber = #ShipTrackingNumber");
sql.AppendLine(", ShipMethodTransmitted = #ShipMethodTransmitted");
sql.AppendLine(", DateShipTransmitProcessed = #DateShipTransmitProcessed");
sql.AppendLine(", ShipmentProcessedBy = #ShipmentProcessedBy");
sql.AppendLine(", Critical = #Critical");
sql.AppendLine(", ShipTransmitStatus = #ShipTransmitStatus");
sql.AppendLine("Where jobtableId = #jobTableId");
cmd.Connection = sqlConnection1;
cmd.CommandText = sql.ToString();
cmd.Parameters.AddWithValue("#TrackingNumber", row.Cells[7].FormattedValue);
cmd.Parameters.AddWithValue("#ShipMethodTransmitted", row.Cells[8].FormattedValue);
cmd.Parameters.AddWithValue("#DateShipTransmitProcessed", row.Cells[9].FormattedValue);
cmd.Parameters.AddWithValue("#ShipmentProcessedBy", row.Cells[10].FormattedValue);
cmd.Parameters.AddWithValue("#Critical", row.Cells[11].FormattedValue);
cmd.Parameters.AddWithValue("#ShipTransmitStatus", row.Cells[13].FormattedValue);
cmd.Parameters.AddWithValue("#jobTableId", row.Cells[5].FormattedValue);
sqlConnection1.Open();
cmd.ExecuteNonQuery();
sqlConnection1.Close();
What I am getting error is that: "Must declare the scalar variable "#ShipTrackingNumber".
I dont want to put ShipTrackingNumber from the code. Instead I want to fetch it from the UI.
What I am doing wrong here?
Well, there's no entry in cmd.Parameters for "#ShipTrackingNumber". What do you mean by "fetch it from the UI"? You could just write a line to add an entry for this parameter:
cmd.Parameters.AddWithValue("#ShipTrackingNumber", GetShipTrackingNumberFromUI());
And then implement GetShipTrackingNumberFromUI() to get the value you want.
It looks like this line is supposed to be something along these lines, but you need to change "#TrackingNumber" to "#ShipTrackingNumber":
cmd.Parameters.AddWithValue("#TrackingNumber", row.Cells[7].FormattedValue);
To answer your direct question, add the parameter with its value taken from the UI. Let's say it's a checkbox named CheckBox1:
cmd.Parameters.AddWithValue("#ShipTrackingNumber", CheckBox1.Checked);
You need to replace this line:
cmd.Parameters.AddWithValue("#TrackingNumber", row.Cells[7].FormattedValue);
with this line:
cmd.Parameters.AddWithValue("#ShipTrackingNumber", row.Cells[7].FormattedValue);
Related
I want to take all the data, (that matches from "name" column) from "barcode" column. Like this:
SELECT barcode FROM table1 where name like 'abc%'
But that doesn't work.
if you mean get barcode based on selected category value, you need to pass the selected value as SqlParameter. ex. in your OnCategoryChanged function,
string queryString =
"SELECT barcode FROM table1 where category=#category;";
using (SqlConnection connection =
new SqlConnection(connectionString))
{
var cmd = new SqlCommand(queryString, connection);
cmd.Parameters.AddWithValue("#category", comboBox1.SelectedValue);
connection.Open();
var reader = cmd.ExecuteReader();
...
// Call Close when done reading.
reader.Close();
}
If anyone would be so kind to send, I am still waiting for an answer. Considering my comments above and below. Thank you...
I am trying to do create a where clause to pass as a parameter to an Oracle command and it's proving to be more difficult than I thought. What I want to do is create a big where query based off user input from our application. That where query is to be the single parameter for the statement and will have multiple AND, OR conditions in it. This code here works however isn't exactly what I require:
string conStr = "User Id=testschema;Password=pass12341;Data Source=orapdex01";
Console.WriteLine("About to connect to Database with Connection String: " + conStr);
OracleConnection con = new OracleConnection(conStr);
con.Open();
Console.WriteLine("Connected to the Database..." + Environment.NewLine + "Press enter to continue");
Console.ReadLine();
// Assume the connection is correct because it works already without the parameterization
String block = "SELECT * FROM TEMP_VIEW WHERE NAME = :1";
// set command to create anonymous PL/SQL block
OracleCommand cmd = new OracleCommand();
cmd.CommandText = block;
cmd.Connection = con;
// since execurting anonymous pl/sql blcok, setting the command type
// as text instead of stored procedure
cmd.CommandType = CommandType.Text;
// Setting Oracle Parameter
// Bind the parameter as OracleDBType.Varchar2
OracleParameter param = cmd.Parameters.Add("whereTxt", OracleDbType.Varchar2);
param.Direction = ParameterDirection.Input;
param.Value = "MY VALUE";
// Get returned values from select statement
OracleDataReader dr = cmd.ExecuteReader();
// Read the identifier for each result and display it
while (dr.Read())
{
Console.WriteLine(dr.GetValue(0));
}
Console.WriteLine("Selected successfully !");
Console.WriteLine("");
Console.WriteLine("***********************************************************");
Console.ReadKey();
If I change the lines below to be the type of result I want then I get an error "ORA-00933: SQL command not properly ended":
String block = "SELECT * FROM TEMP_VIEW :1";
...
...
param.Value = "WHERE NAME = 'MY VALUE' AND ID = 5929";
My question is how do I accomplish adding my big where query dynamically without causing this error?
Sadly there is no easy way to achieve this.
One thing you will need to understand with parameterised SQL in general is that bind parameters can only be used for values, such as strings, numbers or dates. You cannot put bits of SQL in them, such as column names or WHERE clauses.
Once the database has the SQL text, it will attempt to parse it and figure out whether it is valid, and it will do this without taking any look at the bind parameter values. It won't be able to execute the SQL without all of the values.
The SQL string SELECT * FROM TEMP_VIEW :1 can never be valid, as Oracle isn't expecting a value to immediately follow FROM TEMP_VIEW.
You will need to build up your SQL as a string and also build up the list of bind parameters at the same time. If you find that you need to add a condition on the column NAME, you add WHERE NAME = :1 to the SQL string and a parameter with name :1 and the value you wish to add. If you have a second condition to add, you append AND ID = :2 to the SQL string and a parameter with name :2.
Hopefully the following code should explain a little better:
// Initialise SQL string and parameter list.
String sql = "SELECT * FROM DUAL";
var oracleParams = new List<OracleParameter>();
// Build up SQL string and list of parameters.
// (There's only one in this somewhat simplistic example. If you have
// more than one parameter, it might be easier to start the query with
// "SELECT ... FROM some_table WHERE 1=1" and then append
// " AND some_column = :1" or similar. Don't forget to add spaces!)
sql += " WHERE DUMMY = :1";
oracleParams.Add(new OracleParameter(":1", OracleDbType.Varchar2, "X", ParameterDirection.Input));
using (var connection = new OracleConnection() { ConnectionString = "..."})
{
connection.Open();
// Create the command, setting the SQL text and the parameters.
var command = new OracleCommand(sql, connection);
command.Parameters.AddRange(oracleParams.ToArray());
using (OracleDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// Do stuff with the data read...
}
}
}
Below is the code for my Select * Function - It WORKS well and does everything great until i change the SQL string from Select * From Company to
query = "Select * From #1";
and then do the following
query = "Select * From #1";
OleDbCommand Command = new OleDbCommand(query, sqlConnStr);
DataTable Table = new DataTable();
DataSet dataSet = new DataSet();
Table = null;
//Add Parameters
Command.Parameters.AddWithValue("#1", SQLTables.Company);
try
{
Command.ExecuteNonQuery();
adapter.SelectCommand = Command;
adapter.Fill(dataSet);
Table = dataSet.Tables[0];
}
catch (Exception e)
{
MessageBox.Show("A Error occured whilst trying to execute the command.\n" + e.Message);
}
return Table;
The DBMS keeps sending back "Query incomplete" - I assume The Command variable is sending the string query through without changing the Parameter from #1 to Company
Here is a piece of code (mine) where this does work. This is an insert statement rather that a select - Correct me if i am wrong but should it not also work with the SELECT aswell
private void MainActionsInsert(string Action, bool Checked)
{
OleDbCommand Command = new OleDbCommand("INSERT INTO MainActions Values (ID, Action, BoolValue)", DataBaseConnection);
//Add Parameters
Command.Parameters.AddWithValue("ID", GenerateID());
Command.Parameters.AddWithValue("Action", Action);
Command.Parameters.AddWithValue("BoolValue",Checked);
//Add Command
MainActionsAdapter.InsertCommand = Command;
//Execute Agains DataBase
Command.ExecuteNonQuery();
//Accept Changes
}
`
OLEdb doesn't recognize named parameters. You must use ? in the query text.
However, you also can't use dynamic table names with parameterized queries, so even using a ? will not help.
You need to use full dynamic SQL, though that can open you up to SQL Injection. Make sure you read the full article I linked.
OleDbCommand Does accept Parameterized SQL just not in the From Clause - It Has to be either in a WHERE clause or something like that. Like you said it Worked with the insert function because it expects "parameters" there. For example this will work
query = "Select * From Company Where #param = 1";
OleDbCommand Command = new OleDbCommand(query, sqlConnStr);
DataTable Table = new DataTable();
DataSet dataSet = new DataSet();
Table = null;
//Add Parameters
Command.Parameters.AddWithValue("param", "ID");
try
{
Command.ExecuteNonQuery();
adapter.SelectCommand = Command;
adapter.Fill(dataSet);
Table = dataSet.Tables[0];
}
catch (Exception e)
{
MessageBox.Show("A Error occured whilst trying to execute the command.\n" + e.Message);
}
return Table;
Funny though that it doesn't work for the Select part though
I have a few tables in a c# application I'm currently working on and for 4/5 of the tables everything saves perfectly fine no issues. For the 5th table everything seems good until I reload the program again (without modifying the code or working with a seperate install so that the data doesn't go away) The 4/5 tables are fine but the 5th doesn't have any records in it after it has been restarted (but it did the last time it was running). Below is some code excerpts. I have tried a few different solutions online including creating a string to run the sql commands on the database manually and creating the row directly as opposed to the below implementation which uses a generic data row.
//From main window
private void newInvoice_Click(object sender, EventArgs e)
{
PosDatabaseDataSet.InvoicesRow newInvoice = posDatabaseDataSet1.Invoices.NewInvoicesRow();
Invoices iForm = new Invoices(newInvoice, posDatabaseDataSet1, true);
}
//Invoices Table save [Works] (from Invoices.cs)
private void saveInvoice_Click(object sender, EventArgs e)
{
iRecord.Date = Convert.ToDateTime(this.dateField.Text);
iRecord.InvoiceNo = Convert.ToInt32(this.invoiceNumField.Text);
iRecord.Subtotal = (float) Convert.ToDouble(this.subtotalField.Text);
iRecord.Tax1 = (float)Convert.ToDouble(this.hstField.Text);
iRecord.Total = (float)Convert.ToDouble(this.totalField.Text);
iRecord.BillTo = this.billToField.Text;
invoicesBindingSource.EndEdit();
if (newRecord)
{
dSet.Invoices.Rows.Add(iRecord);
invoicesTableAdapter.Adapter.Update(dSet.Invoices);
}
else
{
string connString = Properties.Settings.Default.PosDatabaseConnectionString;
string queryString = "UPDATE dbo.Invoices set ";
queryString += "Date='" + iRecord.Date+"'";
queryString += ", Subtotal=" + iRecord.Subtotal;
queryString += ", Tax1=" + iRecord.Tax1.ToString("N2");
queryString += ", Total=" + iRecord.Total;
queryString += " WHERE InvoiceNo=" + iRecord.InvoiceNo;
using (SqlConnection dbConn = new SqlConnection(connString))
{
SqlCommand command = new SqlCommand(queryString, dbConn);
dbConn.Open();
SqlDataReader r = command.ExecuteReader();
dbConn.Close();
}
}
dSet.Invoices.AcceptChanges();
}
//Invoice Items save [works until restart] (also from Invoices.cs)
private void addLine_Click(object sender, EventArgs e)
{
DataRow iRow = dSet.Tables["InvoiceItems"].NewRow();
iRow["Cost"] = (float)Convert.ToDouble(this.costField.Text);
iRow["Description"] = this.descriptionField.Text;
iRow["InvoiceNo"] = Convert.ToInt32(this.invoiceNumField.Text);
iRow["JobId"] = Convert.ToInt32(this.jobIdField.Text);
iRow["Qty"] = Convert.ToInt32(this.quantityField.Text);
iRow["SalesPerson"] = Convert.ToInt32(this.salesPersonField.Text);
iRow["SKU"] = Convert.ToInt32(this.skuField.Text);
dSet.Tables["InvoiceItems"].Rows.Add(iRow);
invoiceItemsTableAdapter.Adapter.Update(dSet,"InvoiceItems");
PosDatabaseDataSet.InvoiceItemsDataTable dTable = (PosDatabaseDataSet.InvoiceItemsDataTable)dSet.InvoiceItems.Copy();
DataRow[] d = dTable.Select("InvoiceNo=" + invNo.ToString());
invoiceItemsView.DataSource = d;
}
Thanks in advance for any insight.
UPDATE: October 17, 2011. I am still unable to get this working is there any more ideas out there?
you must execute your Sql Command in order to persis the changes you made.
using (SqlConnection dbConn = new SqlConnection(connString))
{
dbConn.Open();
SqlCommand command = new SqlCommand(queryString, dbConn);
command.ExecuteNonQuery();
dbConn.Close();
}
The ExecuteReader method is intended (as the name says) to read the data from a SQL table. You need to use a different method as you can see above.
We need some more info first, you haven't shown the case where your code fails.
Common mistakes on this kind of code is calling DataSet.AcceptChanges() before actually committing the changes to the database.
Second is a conflict between databound data through the binding source vs edits to the dataset directly.
Lets see the appropriate code and we can try and help.
Set a breakpoint after teh call to invoiceItemsTableAdapter and check the InvoiceItems table for the row you have added. Release the breakpoint and then close your app. Check the database again. I would say that another table may be forcibly overwriting the invoice item table.
Consider the following code:
StringBuilder textResults = new StringBuilder();
using(SqlConnection connection = new SqlConnection(GetEntityConnectionString()))
{
connection.Open();
m.Connection = connection;
SqlDataReader results = m.ExecuteReader();
while (results.Read())
{
textResults.Append(String.Format("{0}", results[0]));
}
}
I used Activity Monitor within Sql Server Mgmt Studio on the database to inspect the exact query that was being sent. I then copied that query text to a query editor window within SSMS, and the query returned the expected results. However, SqlDataReader results is always empty, indicating "The enumeration returned no results."
My suspicion is that somehow the results are not being returned correctly, which makes me think there's something wrong with the code above, and not the query itself being passed.
Is there anything that would cause this in the code above? Or something I've overlooked?
EDIT:
Here is the query as indicated by the SQLCommand object:
SELECT DISTINCT StandardId,Number
FROM vStandardsAndRequirements
WHERE StandardId IN ('#param1','#param2','#param3')
ORDER BY StandardId
Here is the query as it appears in Activity Monitor:
SELECT DISTINCT StandardId,Number
FROM vStandardsAndRequirements
WHERE StandardId IN ('ABC-001-0','ABC-001-0.1','ABC-001-0')
ORDER BY StandardId
The query is working against a single view.
When I ran the second query against the database, it returned 3 rows.
The SqlDataReader indicates 0 rows.
try to use Sqldata adapter instead of sqldatreader.
StringBuilder textResults = new StringBuilder();
using (var conn = new SqlConnection(GetEntityConnectionString())))
{
using (
var cmd = new SqlCommand(
"SELECT DISTINCT StandardId,Number" +
"FROM vStandardsAndRequirements " +
"WHERE StandardId IN (#param1,#param2,#param3)" +
"ORDER BY StandardIdl"
, conn))
{
var dSet = new DataSet();
var dt = new Datatable();
var da = new SqlDataAdapter(cmd);
cmd.Parameters.Add("#param1", SqlDbType.VarChar, 50).Value = "ABC-001-0";
cmd.Parameters.Add("#param2", SqlDbType.VarChar, 50).Value = "ABC-001-0.1";
cmd.Parameters.Add("#param3", SqlDbType.VarChar, 50).Value = "ABC-001-0";
try
{
da.Fill(dSet);
dt = dSet.Tables[0];
foreach(Datarow a in dt.Rows)
{
textResults.Append(a["StandardId"].tostring()).AppendLine();
}
Messabox.Show(textResults.tostring);
}
catch (SqlException)
{
throw;
}
finally
{
if (conn.State == ConnectionState.Open) conn.Close();
}
}
}
Regards.
Are you sure it is
WHERE StandardId IN ('#param1','#param2','#param3')
instead of this?
WHERE StandardId IN (#param1,#param2,#param3)
Parameters should not be quoted, not in the SQLCommand object.
Very nice behavior I've observed
I looked for errors in code:
... dr = command.ExecuteReader() ... If dr.Read Then ...
and found that 'dr.Read' works fine, but...
when I mouseover on 'dr', to lookup for data, return values disappeared !
Check your connection string and make sure you are not connecting as a user instance.
http://msdn.microsoft.com/en-us/library/ms254504.aspx