C# How to do loop variable for query (where) - c#

Please help I can't understand about variable for query by when in SQL command. -> get value and do loop again and again (get and change) sorry I'm not good english
This code :
var ee = 0;
var command = new SqlCommand("SELECT Values,date FROM db_db where date ='" + ee ", connection);
var reader = command.ExecuteReader();
var dt = 8;
for (int i = 0; i <= dt; i++)
{
dataGridView1.Columns.Add("A", starttime.AddMonths(i).ToString("MM", seCultureInfo) + "/" + starttime.AddMonths(i).ToString("yyyy", seCultureInfo));
mm = "1";
}
while (reader.Read())
{
var value = reader.GetDecimal(2);
// var column = new DataGridViewTextBoxColumn();
// column.HeaderText = header.ToString();
// this.dataGridView1.Columns.Add(column);
if (dataGridView1.RowCount < 2)
{
this.dataGridView1.Rows.Add();
}
this.dataGridView1.Rows[0].Cells[columnIndex].Value = value;
/* This --------------->*/ ee++;
columnIndex++;
}
Look at "ee". I want to keep value "ee" and bring it back in query command by new "ee".
Last date of value was wrong it's correct at 07/2015

If I got your question correctly , you want to reuse the SQL but increasing the 'ee' variable .
It is impossible .
If your business logic is about query based on different date, You have to build the SQL command again and again .

Related

update a table by using for loop with parameters in C#

I have a table with some columns like
now I want to use a for loop to set
out_0 = 0,
out_1 = 1,
out_2 = 2,
out_3 = 3,
out_4 = 4
so I update it with such code as
string sql = "update exchange_out set #column = #id where member_id = 6;";
SqlCommand cmd = new SqlCommand(sql, connet);
cmd.Parameters.Add("#column", SqlDbType.NVarChar);
cmd.Parameters.Add("#id", SqlDbType.Int);
int n = 0;
for (int i = 0; i < 5; i++)
{
cmd.Parameters["#column"].Value = "out_" + i;
cmd.Parameters["#gid"].Value = i;
n = cmd.ExecuteNonQuery();
MessageBox.Show("" + n);
}
but it didn't write any data into the table while it literally did five times of updating, because the messagebox returns "1" five times.
finally I solve this by
for (int i = 0; i < 5; i++){
sql = string.Format("update exchange_out set {0} = {1} where member_id = 6", "out_" + i, i);
}
but I'm still wondering why it didn't work by adding parameters?
any respond will be appreciated. :)
I'm still wondering why it didn't work by adding parameters?
Identifiers such as table and column names cannot be parameterized in this way, only data. Your attempt effectively runs a query like this:
update exchange_out set 'out_1' = 1 where member_id = 6;
It's the same in any programming language:
var data1 = "hello";
var whichData = "1";
Console.WriteLine(data+whichData); //it doesn't compile; you cannot programmatically build a variable name `data1` in this way
The way you found is reasonably the only way but you should still parameterize the data:
using var cmd = new SqlCommand(sql, connet);
cmd.Parameters.Add("#data", SqlDbType.NVarChar);
cmd.Parameters.Add("#id", SqlDbType.Int);
for (int i = 0; i < 5; i++){
sql = string.Format("update exchange_out set out_{0} = #data where member_id = #id", i);
cmd.CommandText = sql;
cmd.Parameters["#data"].Value = ...
cmd.Parameters["#id].Value = 6;
...
You could also start with an SQL stub like "UPDATE t SET " and repeatedly concatenate on identifiers and parameters:
using var cmd = new SqlCommand(sql, connet);
cmd.Parameters.Add("#data", SqlDbType.NVarChar);
cmd.Parameters.Add("#id", SqlDbType.Int);
var sql = "UPDATE exchange_out SET ";
for (int i = 0; i < 5; i++){
sql += string.Format("out_{0} = #data{0},", i);
cmd.Parameters["#data"+i].Value = ...
}
sql = sql.TrimEnd(',');
sql += " where member_id = #id";
cmd.Parameters["#id"].Value = 6;
cmd.CommandText = sql;
...
This does the update in one operation, running a query like UPDATE t SET out_1 = #data1, out_2 = #data2 ...
These are safe from SQL injection because your code controls the entire SQL; there isn't any capacity for a user to provide '; DROP TABLE Students;-- as the {0} going into the identifier in this case but take care that you don't arrange for it to be possible (don't let the user provide identifier text)..
Your non-parameter attempt is also safe from SQL injection in this case by virtue of inserting intergers that you control, rather than strings you don't, but be careful you don't universally apply the technique and one day include user-suppied strings. If you do find yourself in that suitable you should use something like a whitelist of user input - any string identifier provided by the user that isn't whitelisted should not be put in the SQL

How to return a data from while c# using oracle 11g

I need to return all values from my table. How to write a code inside while?
var stringConnection = "Data Source = X; User Id = X; Password = X";
var sql = "SELECT * FROM TABLE";
OracleConnection _oracleConnection = new OracleConnection(stringConnection);
_oracleConnection.Open();
OracleCommand cmd = new OracleCommand(sql, _oracleConnection);
var dr = cmd.ExecuteReader();
var list = new List<dynamic>();
while(dr.Read())
{
// my doubt is here
}
return list;
var stringConnection = "Data Source = X; User Id = X; Password = X";
var sql = "SELECT * FROM TABLE";
OracleConnection _oracleConnection = new OracleConnection(stringConnection);
_oracleConnection.Open();
OracleCommand cmd = new OracleCommand(sql, _oracleConnection);
var dr = cmd.ExecuteReader();
var list = new List<dynamic>();
while(dr.Read())
{
// **** read column name data from table ****
string Id = (string)dr["Id"];
string company = (string)dr["company"];
string city = (string)dr["City"];
var objItem = new { Id = Id, company = company, city = "city" };
list.Add(objItem);
}
return list;
You have several options. 1 - load DataSet from OracleDataReader. There you will have all your data.
2 - you can still use select *... but you need a model. Then create List<SomeModel> instead of List<dynamic> with
while (reader.Read())
{
model.Property = reader["columnName"]; // will need convert type and take care of DB null. Can use existing extnsions
. . . .
}
3 - For arbitrary number of columns use OracleDataReader.FieldCount and some storage like List<object[]>
var data = new List<object[]>();
var fCnt = reader.FieldCount;
while (reader.Read())
{
var arr = new Object[fCnt];
for(int i = 0; i < fCnt; i++)
arr[i] = reader[i];
data.Add(arr);
}
The unfortunate part with #3 is that in the end you can get jagged array and not 2-dimentional one but you now have enough info to convert it. But I don't remember when I needed to do #3. So think about #1 and #2
And one more thing - absolutely no need for dynamic here. Stay away.

How to count and compare number in datagirdview c#

I have labels "Hardwork" and 1 datagirdview display when load form. I use the code below to do the quantity comparison in the column "TotalTime". I want if the value is in column "TotalTime"> = 30 then labels "Harwork" + 1
but not run.the result is: specified cast is not valid.
Please, help me fix it
public void BtnSearch_Click(object sender, EventArgs e)
{
db = new DbConnector();
lbTotal.Text = "00";
db.fillDataGridView("select *from tbl_WorkLoad where TimeComplete Between'" + dateTimePicker1.Value.ToString("dd-MM-yy| HH:mm:tt") + "' and '" + dateTimePicker2.Value.ToString("dd-MM-yy| HH:mm:tt") + "'", dataGridView1);
const string HardWorkLabelText = "Hard Work Count: {0}";
const int HardWorkThreshold = 30;
try
{
IEnumerable<DataGridViewRow> rows = dataGridView1.Rows.Cast<DataGridViewRow>().Where(r => ((Int32)r.Cells["TotalTime"].Value) >= HardWorkThreshold);
lbHardwork.Text = string.Format(HardWorkLabelText, rows.Count());
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
lbTotaltime.Text = (Convert.ToString(double.Parse(lbTotaltime.Text) + double.Parse(dataGridView1.Rows[i].Cells[7].Value.ToString())));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
You have apart from the exception, you have few other issues in the code. But let us focus on the issue which you reported.
From the code, I understand that, you want to display the number of hardwork and also you want to display the total hardwork time.
Since you are looping thru the rows of gridview, you can calculate both of these in the for loop.
var hardworkCount = 0;
var totalTimeSum = 0.0;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
double totalTime = double.Parse(dataGridView1.Rows[i].Cells[7].Value.ToString());
if(totalTime >= HardWorkThreshold)
{
hardworkCount++;
}
totalTimeSum += totalTime;
}
lbHardwork.Text = hardworkCount.ToString();
lbTotaltime.Text = totalTimeSum.ToString();
You life would be a lot simpler if you stop pulling your data out of the datagridview, and just have your datagridview based off a datatable that holds the data. It might be this way already, but we can't see the definition of your filldatagridview method
Here's how I'd do it:
//assuming sql sevrer, use correct dataadapter for your db
using(var da = new SqlDataAdapter "select * from tbl_WorkLoad where TimeComplete Between #a and #b", "YOUR CONNECTION STRING HERE")){
da.SelectedCommand.Parameters.AddWithValue("#a", dateTimePicker1.Value);
da.SelectedCommand.Parameters.AddWithValue("#b", dateTimePicker2.Value);
var dt = new DataTable();
da.Fill(dt);
dataGridViewX.DataSource = dt;
lbHardwork.Text = dt.Compute("Count([TotalTime])", "[TotalTime] >= 30").ToString();
lbTotalTime.Text = dt.Compute("Sum([TotalTime])", "[TotalTime] >= 30").ToString();
}
The way you wrote your SQL is a pattern that risks SQL injection if used with strings - always use parameters in SQL. Always. There is never a reason not to when dealing with data values. See why, and also here
You should read this blog before using AddWithValue with strings in SQL Server. There are better ways to do parameters than AWV, but at the very least it would be preferable to use AddWithValue than what you're doing now
Don't access data in a gridview via the grid; bind the grid to a datatable and if you want data, access the datatable. If you want to get the datatable out of a grid at any point, you can use var dt = datagridviewX.DataSource as DataTable

C# Excel add-in loops never terminate

I have written an add-in that reads values from a spreadsheet and populates a database. When I execute the add-in in debug mode from Visual studio it works correctly the first time. Without stopping the debugger when I try to upload values from another spreadsheet using the add-in the loops in my add-in never seem to end. I control them using the used range of the active sheet and for some reason after the loop counter hits the range count it gets reinitialized to the starting value and hence my database spits out an SqlException due to a violation of the unique key constraint.
using (SqlConnection conn = DataConnection.GetConnection())
{
conn.Open();
using (SqlCommand myCommand = new SqlCommand(commandText, conn))
{
SqlParameter termIDParam = myCommand.Parameters.Add("#tid", SqlDbType.Int);
SqlParameter priceParam = myCommand.Parameters.Add("#price", SqlDbType.Decimal);
SqlParameter ContractDateParam = myCommand.Parameters.Add("#date", SqlDbType.DateTime);
SqlParameter pipelineIDParam = myCommand.Parameters.Add("#pid", SqlDbType.Int);
string pipeline = activeSheet.Cells[1, 1].Value2.ToString();
bool isNonDuplicate = true;
int startRow = (pipeline.ToLower().Equals("henry hub")) ? 3 : 4;
int startColumn = checkBox1.Checked ? 2 : 1;
for (int i = startRow; i <= range.Rows.Count & isNonDuplicate; i++)
{
for (int j = startColumn; j <= range.Columns.Count; j++)
{
if (range.Cells[i, j].Value2 != null && !range.Cells[i, j].Value2.ToString().Equals(" "))
{
string dateval = range.Cells[(startRow - 2), j].Value2.ToString();
double val = double.Parse(dateval);
DateTime contractDate = DateTime.FromOADate(val);
DateTime tempTerm = DateTime.FromOADate(activeSheet.Cells[i, 1].Value2);
string monthName = new DateTimeFormatInfo().GetAbbreviatedMonthName(tempTerm.Month);
string year = tempTerm.Year.ToString().Substring(2, 2);
string term = monthName + "-" + year;
double price = double.Parse(range.Cells[i,j].Value2.ToString());
SqlCommand subCommand = new SqlCommand();
subCommand.CommandText = "Select PipelineID from Pipeline where PipelineDescription='" + pipeline + "'";
subCommand.Connection = conn;
int pipeID = (int)subCommand.ExecuteScalar();
subCommand.CommandText = "Select TermID from Term where TermDescription = '" + term + "'";
int termID = (int)subCommand.ExecuteScalar();
termIDParam.Value = termID;
priceParam.Value = price;
ContractDateParam.Value = contractDate;
pipelineIDParam.Value = pipeID;
myCommand.Parameters["#tid"] = termIDParam;
myCommand.Parameters["#price"] = priceParam;
myCommand.Parameters["#date"] = ContractDateParam;
myCommand.Parameters["#pid"] = pipelineIDParam;
myCommand.ExecuteNonQuery();
}
}
double progress = (double)i / range.Rows.Count * 100;
bgw.ReportProgress(Convert.ToInt32(progress));
}
}
}
The i loop after it hits the limit(range.rows.count) gets reinitalised to 'startRow' and it happens only when I dont stop the debugger after processing one sheet and continue processing multiple sheets.
I am at my wits end tring to figure out what could cause this. Please help
Update
I forgot to add that this method is part of the Background Worker DoWork() method. When I try to execute it without using background worker I have no issues. I am forced to think the DoWork () method does not end and keeps calling the method causing the reinitialization. How can I let the DoWork method know that the work is over.

Passing Column name as string in mysql Insert query

this is what i am trying to do after receiving string from the serial port. i get whitespace between the data so i put two loops to eliminate them. i want to recieve data spanning multiple columns and a single row for every single run of do while loop.. Thanks in Advance
string text = sp.readline();
for (int i = 0; i < text.Length; )
{
p = text[i].ToString();
if (p != " ")
{
do
{
x += text[i].ToString();
s = text[i].ToString();
i++;
} while (s != " ");
try
{
string col = "column" + no.ToString();
MySqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO testdata("+col+")VALUES(?data)";
cmd.Parameters.Add("?data", MySqlDbType.VarChar).Value = x;
cmd.ExecuteNonQuery();
x = "";
p = "";
no++;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
} i++;
}
Sorry to say, you cannot, in any dialect of SQL, provide a table or column name as a bindable variable (or parameter). If it's working for MySQL that's terrific, but if you change over to any other DBMS make and model, it will suddenly stop working.
Also, INSERT means create a new row. You'll either need to insert all the column values at once in a single INSERT statement, or figure out how to INSERT one row and then UPDATE it for each new column value.
if you want to insert a single row having multiple column, then for loop is not required
following is for three columns
int no = 2;
cmd.CommandText = "INSERT INTO testdata(?col1,?col2,?col3)VALUES(?data1,?data2,?data3)";
cmd.Parameters.Add("?col1", MySqlDbType.String).Value = col1;
cmd.Parameters.Add("?col2", MySqlDbType.String).Value = col2;
cmd.Parameters.Add("?col3", MySqlDbType.String).Value = col3;
cmd.Parameters.Add("?data1", MySqlDbType.VarChar).Value = x1;
cmd.Parameters.Add("?data2", MySqlDbType.VarChar).Value = x2;
cmd.Parameters.Add("?data3", MySqlDbType.VarChar).Value = x3;
cmd.ExecuteNonQuery();

Categories