Save in a variable and multiply double value query result C#/MySql - c#

I'm trying to save the unique value resulting from a query into a double variable, since the same is stored in the database as double, so I can later be able to multiply it with a counter, with the following code:
public partial class CoronaClaraCant : Form
{
private int conteoCliks = 0;
private string producto = "CoronaClara";
private double precio;
public CoronaClaraCant()
{
InitializeComponent();
}
private void CoronaClara_Click(object sender, EventArgs e)
{
MySqlConnection conn = new MySqlConnection("server=localhost;database=database;username=root;password=***");
conn.Open();
string select = "SELECT precio FROM productos where prodnom = '" + producto + "';";
MySqlCommand cmd = new MySqlCommand(select, conn);
double result = cmd.ExecuteNonQuery();
conteoCliks++;
precio = result;
double total = (precio * conteoCliks);
lblcantidad.Text = conteoCliks.ToString();
lblprecio.Text = precio.ToString();
lbltotal.Text = total.ToString();
}
}
So far I've only been getting negative values:
I'm guessing this could be because the ExecuteNonQuery, but I haven't been able to assign a double value to a ExecuteScalar method, and I'm not sure if there are other parameters I should consider when saving a double value into a variable.

You want to select data from database and you are calling ExecuteNonQuery which is used for Insert,Update or Delete commands.
You need to call ExecuteReader or if you want to get data in a DataTable you can fill a DataTable.
SqlDataReader rdr = cmd.ExecuteReader();
if (rdr.HasRows)
{
if (rdr.Read())
{
precio = (double)rdr["precio"];
}
}

Related

How can I solve System.Data.OleDb.OleDbException: 'Syntax error in FROM clause.'

I run the VS file to the following code. After start running, it shows System.Data.OleDb.OleDbException: 'Syntax error in FROM clause.'
How can I solve it? Thank you.
public partial class OrderForm : Form
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=db_users.accdb");
OleDbCommand command = new OleDbCommand();
OleDbDataReader dr;
public OrderForm()
{
InitializeComponent();
LoadOrder();
}
public void LoadOrder()
{
double total = 0;
int i = 0;
dgvOrder.Rows.Clear();
command = new OleDbCommand("SELECT OrderID,OrderDate,O.[ProductID],P.[ProdName], O.[CustID], C.[CustName], Qty, Price, Total FROM [Order] AS O JOIN [Customer] AS C ON O.[CustID]=C.[CustID] JOIN [Product] AS P ON O.[ProductID]=P.[ProductID] WHERE CONCAT(OrderID,OrderDate,O.[ProductID],P.[ProdName], O.[CustID], C.[CustName]) LIKE '%" +txtSearch.Text+"%'", con);
con.Open();
dr = command.ExecuteReader();
while (dr.Read())
{
i++;
dgvOrder.Rows.Add(i, dr[0].ToString(), Convert.ToDateTime(dr[1].ToString()).ToString("dd/MM/yyyy"), dr[2].ToString(), dr[3].ToString(), dr[4].ToString(), dr[5].ToString(), dr[6].ToString(), dr[7].ToString(), dr[8].ToString());
total += Convert.ToInt32(dr[8].ToString());
}
dr.Close();
con.Close();
lblQty.Text = i.ToString();
lblTotal.Text = total.ToString();
}
with the information provided by your code, I have created 3 tables to simply reproduce your code.The data in the table in the database is filled in casually, please understand.
form page:
By clicking the "Query Condition" button, you can generate data in the form by querying the database.
this is the result:
The operation of the database is encapsulated by the entity class, which is the code that encapsulates the database entity class.
internal class Dao
{
SqlConnection conn;
public SqlConnection connection()
{
// write database connection string
string connStr = "Data source=localhost;Initial Catalog=test;User ID=sa;Password=123456";
conn = new SqlConnection(connStr);
conn.Open();
return conn;
}
public SqlCommand command(string sql)
{
SqlCommand cmd = new SqlCommand(sql, connection());
return cmd;
}
public int Execute(string sql)
{
return command(sql).ExecuteNonQuery();
}
public SqlDataReader read(string sql)
{
return command(sql).ExecuteReader();
}
public void DaoClose()
{
conn.Close();
}
}
By clicking the button, the function of querying the database is realized and the corresponding data is generated.
//Read the data from the data and display it in the table control
public void Table()
{
dataGridView1.Rows.Clear();// clear old data
Dao dao = new Dao();
double total = 0;
int i = 0;
string sql = $"SELECT OrderID,OrderDate,O.[ProductID],P.[ProdName], O.[CustID], C.[CustName], Qty, Price, Total FROM [Orders] AS O JOIN [Customer] AS C ON O.[CustID]=C.[CustID] JOIN [Product] AS P ON O.[ProductID]=P.[ProductID] WHERE CONCAT(OrderID,OrderDate,O.[ProductID],P.[ProdName], O.[CustID], C.[CustName]) LIKE '%{textBox1.Text}%'";
IDataReader dr = dao.read(sql);
while (dr.Read())
{
i++;
dataGridView1.Rows.Add(i, dr[0].ToString(), Convert.ToDateTime(dr[1].ToString()).ToString("dd/MM/yyyy"), dr[2].ToString(), dr[3].ToString(), dr[4].ToString(), dr[5].ToString(), dr[6].ToString(), dr[7].ToString(), dr[8].ToString());
total += Convert.ToInt32(dr[8].ToString());
}
dr.Close();
dao.DaoClose();
lblQty.Text = i.ToString();
lblTotal.Text = total.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
Table();
}
Through the test, there is no problem with the sql statement, the function of database query is realized and the data is successfully displayed. Check the database connection string. Whether the fields of the sql statement correspond to the database. Hope that helps you.

This C# / sql query code takes a lot of time to update the table

Can anyone help improve performance? Updating the table takes a lot of time.
I am updating the serial number from datagridview to a table called dbo.json
// UPDATE dbo.json with numbers
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
string VAL1;
string VAL2;
foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
if (string.IsNullOrEmpty(row.Cells[5].Value as string))
{
}
else
{
for (int i = 0; i <= DgvWhistlSorted.Rows.Count - 2; i++)
{
VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();
var cnn = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;
using (var con = new SqlConnection(cnn))
{
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "UPDATE dbo.json SET RowN = #VAL1 WHERE [A-order] = #VAL2";
cmd.Parameters.AddWithValue("#VAL1", VAL1);
cmd.Parameters.AddWithValue("#VAL2", VAL2);
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
MessageBox.Show("dbo.json is ready");
}
You shouldn't create the connection and command inside such a tight loop - create and open the connection and command ONCE before the loop, and in the loop, only set the parameter values and execute the query for each entry.
Something like this:
// UPDATE dbo.json with numbers
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
string VAL1;
string VAL2;
// define connection string, query text *ONCE* before the loop
string cnn = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;
string updateQuery = "UPDATE dbo.json SET RowN = #VAL1 WHERE [A-order] = #VAL2;";
// create connection and command *ONCE*
using (SqlConnection con = new SqlConnection(cnn))
using (SqlCommand cmd = new SqlCommand(updateQuery, cnn))
{
// Define parameters - adapt as needed (don't know the actual datatype they have)
cmd.Parameters.Add("#VAL1", SqlDbType.VarChar, 100);
cmd.Parameters.Add("#VAL2", SqlDbType.VarChar, 100);
// open connection ONCE, for all updates
con.Open();
foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
{
if (!string.IsNullOrEmpty(row.Cells[5].Value as string))
{
for (int i = 0; i <= DgvWhistlSorted.Rows.Count - 2; i++)
{
VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();
// set the values
cmd.Parameters["#VAL1"].Value = VAL1;
cmd.Parameters["#VAL2"].Value = VAL2;
// execute query
cmd.ExecuteNonQuery();
}
}
}
// close connection after all updates are done
con.Close();
}
MessageBox.Show("dbo.json is ready");
}
Create the connection ONCE...you're creating a new database connection each time through the loop! And in fact you do not need to create new command objects each time. You can reuse the command object because the parameters are the same. Just clear the params each time through the loop.
Also don't do the grid view count in the loop, set a variable for it.
string query = "UPDATE dbo.json SET RowN = #VAL1 WHERE [A-order] = #VAL2";
int counter = DgvWhistlSorted.Rows.Count - 2;
using (SqlConnection con = new SqlConnection(cnn))
{
con.Open();
using(SqlCommand cmd = new SqlCommand(cnn,query))
{
cmd.Parameters.Clear();
//Do your loop in here
for (int i = 0; i <= counter; i++)
{
VAL1 = DgvWhistlSorted.Rows[i].Cells[6].Value.ToString();
VAL2 = DgvWhistlSorted.Rows[i].Cells[0].Value.ToString();
cmd.Parameters.AddWithValue("#VAL1", VAL1);
cmd.Parameters.AddWithValue("#VAL2", VAL2);
cmd.ExecuteNonQuery();
}
}
}
A better idea is to do this in one command, by passing all the data in a Table-Value Parameter (TVP):
First create the table type. I don't know your data types, so I'm guessing here. Make sure to match the types to the existing table.
CREATE TYPE dbo.OrderJson (
Order int PRIMARY KEY,
RowN nvarchar(max) NOT NULL
);
Then you can pass the whole thing in one batch. You need to create a DataTable to pass as the parameter, or you can use an existing datatable.
// UPDATE dbo.json with numbers
private void BtnUpdateSql_Click(object sender, EventArgs e)
{
var table = new DataTable {
Columns = {
{ "Order", typeof(int) },
{ "RowN", typeof(string) },
},
};
foreach (DataGridViewRow row in DgvWhistlSorted.Rows)
if (!string.IsNullOrEmpty(row.Cells[5].Value as string))
table.Rows.Add(DgvWhistlSorted.Rows[i].Cells[0].Value, DgvWhistlSorted.Rows[i].Cells[6].Value)
const string query = #"
UPDATE dbo.json
SET RowN = t.RowN
FROM dbo.json j
JOIN #tmp t ON t.order = j.[A-order];
";
using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["sql"].ConnectionString))
using (var cmd = new SqlCommand(query, con))
{
cmd.Parameters.Add(new SqlParameter("#tmp", SqlDbType.Structured) { Value = table, TypeName = "dbo.OrderJson" });
con.Open();
cmd.ExecuteNonQuery();
}
MessageBox.Show("dbo.json is ready");
}
I found that the fastest way would be to save the DATAGRIDVIEW to an SQL table and continue the process with - stored procedure + update query - between two tables - now it flies ...
Thank you all

I want to get the project balance after project amount is subtract to project cost. using decimal c#

First Process is to get value on database and search the Project Amount. after dislplaying it in amount.Text here is the code in search button
private void ButSearchGet_Click(object sender, EventArgs e)
{
if (textBox6.Text == "")
{
MessageBox.Show("Invalid Please Input Control #..");
clear2();
}
else
{
SqlCommand cmd = new SqlCommand("select * from tbl_expense WHERE Contract_ID Like'%' +#Contract_ID+ '%'", conn);
cmd.Parameters.AddWithValue("Contract_ID", textBox6.Text);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
DataTable dt = new DataTable();
da.Fill(dt);
datagridview.DataSource = dt;
this.datagridview.Columns["id"].Visible = false;
conn.Open();
SqlCommand cm = new SqlCommand("select * from tbl_expense where contract_id=#contract_id ", conn);
cm.Parameters.AddWithValue("contract_id", textBox6.Text);
SqlDataReader rdr;
rdr = cm.ExecuteReader();
if (rdr.Read())
{
lblid.Text = rdr["CONTRACT_ID"].ToString();
lblcontractor.Text = rdr["CONTRACTOR"].ToString();
lblstatus.Text = rdr["PROJECT_STATUS"].ToString();
lblstart.Text = rdr["COVERED_PERIOD"].ToString();
lblend.Text = rdr["END_PERIOD"].ToString();
amount.Text = Convert.ToDecimal(rdr["PROJECT_AMOUNT"]).ToString("C", CultureInfo.CreateSpecificCulture("en-PH")); // here is the code to get decimal amount in database and throw to amount.Text it will display ex. ₱48,000,000.00
lblcons.Text = rdr["CONTRACT"].ToString();
label32.Text = rdr["id"].ToString();
projectid.Text = rdr["projectid"].ToString();
}
else
{
MessageBox.Show("No Data Exist");
clear2();
}
conn.Close();
refresh();
}
}
now the next step is to sum the project costs amount in the database i created a button to trigger function to sum all the project cost and display it to lblcost.Text. here is the code below
private void butGenerateExpense(object sender, EventArgs e)
{
decimal sum;
decimal subTotal = 0;
decimal subTotal1 = 0;
if (this.datagridview.Rows.Count > 0)
{
foreach (DataGridViewRow row in this.datagridview.Rows)
{
if (row.Cells[7].Value != null && !string.IsNullOrEmpty(row.Cells[7].Value.ToString()))
{
subTotal += Convert.ToDecimal(row.Cells[7].Value);
}
}
this.lbl1.Text = subTotal.ToString("C", CultureInfo.CreateSpecificCulture("en-PH"));
}
if (this.datagridview.Rows.Count > 0)
{
foreach (DataGridViewRow row in this.datagridview.Rows)
{
if (row.Cells[12].Value != null && !string.IsNullOrEmpty(row.Cells[12].Value.ToString()))
{
subTotal1 += Convert.ToDecimal(row.Cells[12].Value);
}
}
this.lbl2.Text = subTotal.ToString("C", CultureInfo.CreateSpecificCulture("en-PH"));
}
sum = subTotal + subTotal1;
textTotal.Text = sum.ToString("C", CultureInfo.CreateSpecificCulture("en-PH"));
Now it will display the total project cost in lblcost.Text after click the button to generate the expense.
here is my concern i want to Subtract the project Amount and project Cost and display the project Balance in the lblbalance.Text i want the the value and convert into decimal but i got this error and logic since it was being get search first in a process.
my first Code attempt is this.
private void butGenerateExpense(object sender, EventArgs e)
{
decimal a, b, diff;
a = Convert.ToDecimal(amount.Text);
b = Convert.ToDecimal(textTotal.Text);
diff = a - b;
lblbalance.Text = diff.ToString("C", CultureInfo.CreateSpecificCulture("en-PH"));
after pressing the button generate expense together with the codes to get the project cost.
The Error: System.FormatException: 'Input string was not in a correct format.'
If you convert the numbers to text using a specific culture, you need to use the same culture when parsing the text. See the TryParse overload that takes a IFormatProvider, i.e. a cultureInfo.
decimal.TryParse(textTotal.Text, NumberStyles.Currency, CultureInfo.CreateSpecificCulture("en-PH"), out var result);
If you are converting strings to numbers for anything other than input or deserializing, or the other way around, you are doing something wrong. Try to keep the numbers as decimal values as long as possible. A common approach is to use a property with a backing field, with a setter that also updates the corresponding text-box.

How to fetch data in a variable in asp.net C#

I am trying to fetch the data in a decimal variable. I highly need your assistance to do so. if I test the query but put the fetched value in the label, it works without any problem. However, I want to get it in the decimal humidity as I want to compare this value with the threshold. Could you help me with this? Your help with being highly appreciated
below is the code
the output: I still get 20 which is the declared value in the code.
namespace IoTSmartFarming
{
public partial class DataVisualization : System.Web.UI.Page
{
string strcon = ConfigurationManager.ConnectionStrings["conn"].ConnectionString;
protected void Page_Load(object sender, EventArgs e)
{
showHumidity();
}
private decimal getHumidity()
{
SqlConnection conn = new SqlConnection(strcon);
if (conn.State == System.Data.ConnectionState.Closed)
{
conn.Open();
}
decimal humidity = 20;
SqlCommand cmd = new SqlCommand("SELECT TOP 1 value from Humidity ORDER BY time desc", conn);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Label4.Text= dr.GetValue(0).ToString();
}
return humidity;
}
private void showHumidity()
{
decimal actHumidity = getHumidity();
Label4.Text = actHumidity.ToString();
if(actHumidity>100 || actHumidity < 10)
{
Label5.Visible = false;
Label6.Visible = true;
}
}
}
}
You forgot to assign your variable. All that you need is add an variable assignment:
humidity = dr.GetDecimal(0);

how to create an id to be shown in the text box based on selected dropdownlist

i would like to create an id generator based on their department selected from the dropdownlist. lets say my ddl has 3 departments (A,B,C) and when generating an id it will be A20181001 and then A20181002 upon submission but when i pick B from the ddl after sending A20181001 to the database, it will be B20181001.
so far i have created the code for the increment for the id without the departments. here is the code i did so far. (I used the date for today so the 20181001 is just an example):
void getMRF_No()
{
string year = DateTime.Now.Date.ToString("yyyyMMdd");
int mrf = 0;
int i;
string a;
//string x = Request.QueryString["BUnit"];
string mrfNo = "";
database db = new database();
string conn = dbe.BU();
SqlConnection connUser = new SqlConnection(conn);
SqlCommand cmd = connUser.CreateCommand();
SqlDataReader sdr = null;
string query = "SELECT TOP 1 MRF_NO FROM incMRF ORDER BY MRF_NO DESC";
connUser.Open();
cmd.CommandText = query;
sdr = cmd.ExecuteReader();
while (sdr.Read())
{
mrfNo = sdr.GetInt32(0).ToString();
}
if (mrfNo == "")
{
mrfNo = Convert.ToString(year) + "" + 00;
}
mrf += 0;
i = Convert.ToInt32(mrfNo) + 1;
a = i.ToString();
txtMRFNo.Text = a;
connUser.Close();
}
any help to improve this code will be helpful. thank you :)
EDIT:
here is the dropdown list code:
void SelectBU()
{
string database = dbe.BU ();
using (SqlConnection con = new SqlConnection(database))
{
con.Open();
string query = "select BUnit from BusinessUnit";
using (SqlDataAdapter sda = new SqlDataAdapter(query, con))
{
DataSet ds = new DataSet();
sda.Fill(ds, "BUnit");
ddlBu.DataSource = ds;
ddlBu.DataTextField = "BUnit";
ddlBu.DataValueField = "BUnit";
ddlBu.DataBind();
selectOption(ddlBu, "Select Dept");
}
con.Close();
}
}
EDIT2: I will state what im searching for here incase some doesnt know or understand. What i want is upon selecting a department from a dropdownlist, for example i picked A. the textbox show show A2018102201. if i select B it should show B2018102201 and if its C then c2018102201. and it will change its number once i submit it to a database and a new form loads. So if A2018102201 is already in the database, then the text shown in the text box will be A2018102202. BUT if i select B then the textbox will show B2018102201 since it does not exist in the database yet.
First you should get max ID, then increase the numeric part of your Id, and If this is a multi-user application, you have to lock your table, because it might create many ID duplication, Therefore I'm not recommend to create ID like this on c#, it is better to create a Sequence on SQL server. but I wrote this sample for you, just call it with proper value.
static string getMRF_No(string prefixCharFromDropDownList)
{
string year = DateTime.Now.Date.ToString("yyyyMMdd");
string mrfNo = "";
SqlConnection connUser = new SqlConnection("Server=130.185.76.162;Database=StackOverflow;UID=sa;PWD=$1#mssqlICW;connect timeout=10000");
SqlCommand cmd = new SqlCommand(
$"SELECT MAX(MRF_NO) as MaxID FROM incMRF where MRF_NO like '{prefixCharFromDropDownList}%'"
,connUser
);
connUser.Open();
SqlDataReader sdr = cmd.ExecuteReader();
while (sdr.Read())
{
mrfNo = sdr["MaxID"].ToString();
}
if (mrfNo == "")
{
mrfNo = prefixCharFromDropDownList + year + "000";
}
else
{
mrfNo = prefixCharFromDropDownList + (long.Parse(mrfNo.Substring(1)) + 1).ToString().PadLeft(2);
}
sdr.Close();
cmd = new SqlCommand($"INSERT INTO incMRF (MRF_NO) values ('{mrfNo}')",connUser);
cmd.ExecuteNonQuery();
connUser.Close();
//txtMRFNo.Text = prefixCharFromDropDownList + i.ToString();
return mrfNo;
}
I call this method on a console application as test.
static void Main(string[] args)
{
// send dropdown (selected char) as prefix to method
var newAId = getMRF_No("A");
var newAnotherAId = getMRF_No("A");
var newBId = getMRF_No("B");
var newAnotherAId2 = getMRF_No("A");
Console.ReadKey();
}

Categories

Resources