sql query to show data from price between two columns C# - c#

EDIT: I am not able to format my code below, if any one can fix it.
I am new to sql queries and still learning.
Table Name: CommissionSetupTable.
I want to display #Paisa if gross_amount is between the range of #FromRate and #ToRate
Below is my code:
string paisa;
private void load_commission_setup()
{
SqlCeConnection conn = null;
SqlCeCommand cmd = null;
SqlCeDataReader rdr = null;
try
{
conn =
new SqlCeConnection(
#"Data Source=|DataDirectory|\Database.sdf;Persist Security Info=False");
conn.Open();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
gross_amount = double.Parse(purchaseBillTableDataGridView[10, rowindex].Value.ToString());
// Gross Amount is between the ranges of FromRate and ToRate.
cmd = new SqlCeCommand("SELECT Paisa FROM CommissionSetupTable WHERE='" + gross_amount.ToString() + "' BETWEEN #FromRate AND #ToRate;", conn);
rdr = cmd.ExecuteReader();
if (rdr == null)
{
}
else
{
while (rdr.Read())
{
paisa = rdr["Paisa"].ToString();
}
rdr.Close();
cmd.Dispose();
}
}
finally
{
conn.Close();
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
purchaseBillTableDataGridView[11, rowindex].Value = paisa;
}
}

The correct syntax to use here is the following
cmd = new SqlCeCommand(#"SELECT Paisa FROM CommissionSetupTable
WHERE #gross BETWEEN FromRate AND ToRate;", conn);
Notice that the two field names should not be prefixed with #, otherwise they will be considered parameters placeholders.
And now, before executing the command, add the parameter for the #gross placeholder
cmd.Parameters.Add("#gross", SqlDbType.Decimal).Value = gross_amount;
I don't know what is the exact datatype of the columns FromRate and EndRate, but
note that you should use the correct datatype for your parameter. Do not pass a string and expect the database engine do the conversion for you. (or worse concatenate your value to the rest of the sql using ToString()). This is always wrong also if sometime the database engine could understand your values.
EDIT
Also, following your comments below, it appears that this line is wrong
int rowindex = purchaseBillTableDataGridView.Rows.Count - 1;
If your DataGridView has the property AllowUserToAddRow set to True then you want to use
int rowindex = purchaseBillTableDataGridView.Rows.Count - 2;
because the first line points to the empty row added to the DataGridView for inserting a new record.

Related

Char '00' not converting to int 01 from SQL Server in C#

I am fetching a column from database of char(2) data type.
On an Event, I am changing the char data type to int and incrementing it by 1, with this code:
int i = 0;
using (SqlConnection sqlCon = new SqlConnection(Login.connectionString))
{
string commandString = "SELECT MAX(CAST(Category_Code as INT)) FROM Category;";
SqlCommand sqlCmd = new SqlCommand(commandString, sqlCon);
sqlCon.Open();
SqlDataReader dr = sqlCmd.ExecuteReader();
while (dr.Read())
{
i = 1;
if (dr[0] == null)
{
Ctgry_CtgryCodeCb.Text = "1";
}
else
{
int cat_next_code = int.Parse(dr[0].ToString());
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();
}
}
}
It is working properly but not for the first time (doesn't add 1 to empty or 0) as column is empty.It shows some error that it is not is correct format to convert. I also set the default value of the column to 0, but it shows ((0)) as default value.
Any help would be appreciated.
If you are using this code to increment primary key value of the database table, you shouldn't be doing this way. You should be using IDENTITY column feature available in the database.
Since you have not explained why you are not using IDENTITY column, looks like this code is for some other purpose.
As per your code you are getting Maximum value of some column from the database and incrementing it by one in the code.
When the table in the database is empty you not get anything is the reader. So While loop will not be executed at all. So even if you are checking for NullOrEmpty inside the while loop, it will never get executed.
Also you don't need to use SqlDataReader here. Since you are returning only one single value from the query you can use ExecuteScalar method of SqlCommand and get that value. It will be simpler.
var codeFromDb = sqlCmd.ExecuteScalar();
var cat_next_code = 0;
if(!(codeFromDb is DBNull))
{
cat_next_code = Convert.ToInt32(codeFromDb);
}
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();
My strong recommendation is to use IDENTITY column instead of doing all this code.
This will help you resolve your current issue.
SqlDataReader is overkill in this case and I don't like to answer for the wrong approach but since you insist consider following.
SqlDataReader dr = sqlCmd.ExecuteReader();
int cat_next_code = 0;
if(dr.Read()) // while is not needed here. There will be only one row in the reader as per the query.
{
i = 1;
if(!dr.IsDBNull(0))
{
cat_next_code = int.Parse(dr[0].ToString());
}
}
Ctgry_CtgryCodeCb.Text = (cat_next_code + 1).ToString();

Auto generate and AutoIncrement ID in C# when trying to add new record to database

I'm using this code to select the maxID from a database table and each time I want to add a new record, the autogenerated ID is not the last one +1.
public formularAddCompanie()
{
InitializeComponent();
try
{
string cs = "Data Source=CODRINMA\\CODRINMA;Initial Catalog=TrafficManager;Integrated Security=True";
string select = "SELECT max(IDCompanie) FROM Companii";
using (SqlConnection con = new SqlConnection(cs))
{
con.Open();
SqlCommand cmd2 = new SqlCommand(select, con);
SqlDataReader sda = cmd2.ExecuteReader();
DataTable idmax = new DataTable("idmax");
idmax.Load(sda);
if (idmax.Rows[0][0].ToString().Trim() == "") { txtID.Text = "1"; }
else { txtID.Text = (int.Parse(idmax.Rows[0][0] .ToString() + 1).ToString()); }
}
}
catch (Exception er) { MessageBox.Show(er.Message); }
}
The table from where the selection is made, looks like this:
IDCompany Name Address City RegNo
1 A Street NY 123
Each time I want to add a new record, the autogenerated ID is like this: 11, 111, 1111. It takes the last ID and add another 1 next to it. What am I missing?
Interestingly, note that
string a = "The meaning of life is " + 42;
converts 42 to a string, creating the result
a == "The meaning of life is 42"
Look at this code:
(int.Parse(idmax.Rows[0][0] .ToString() + 1).ToString()); }
You are converting idmax.Rows[0][0] to a string and adding +1 to the end of the string rather than to an integer value. Try
(int.Parse(idmax.Rows[0][0].ToString()) + 1).ToString(); }
Note that idmax.Rows[0][0] should already have an integer in it (as pointed out in the comments). If that's the case, you can simplify to
(idmax.Rows[0][0] + 1).ToString(); }
idmax.Rows[0][0].ToString() + 1 produces string, not int.
You can try
txtID.Text = (Convert.ToInt32(idmax.Rows[0][0]) + 1).ToString();
I just add this because it seems that none cares about the weakness of the code posted by the poster.
First the MAX function is not reliable if you want to find the next autoincrement value that will be assigned to an ID column. Concurrency could wreak havoc with any schema that use MAX. Just suppose that another user has already retrieved the MAX for its own INSERT operation, then depending on the relative speed of the two computers you or the other user will insert a duplicate value for the IDCompany field.
The only correct way to do this common task is to use the IDENTITY property for the column IDCompany and when you need to insert a new record you should write something like this
try
{
string insert = "INSERT INTO Companii (Name,Address,City,RegNo)
VALUES(#name,#address,#city,#regno);
SELECT SCOPE_IDENTITY()";
using (SqlConnection con = new SqlConnection(cs))
using (SqlCommand cmd = new SqlCommand(insert, con))
{
con.Open();
cmd.Parameters.Add("#name", SqlDbType.NVarChar).Value = txtBoxCity.Text;
.... and on for the other parameters ....
int companyID = Convert.ToInt32(cmd.ExecuteScalar());
... work with the just added company if required
}
}
catch (Exception er)
{ MessageBox.Show(er.Message); }
SCOPE_IDENTITY will return the last identity value inserted into an identity column in the same scope and in this context scope means the connection used by your command.
In any case, if the MAX approach is still required then the code could be simplified a lot using a modified query and SqlCommand.ExecuteScalar instead of building an SqlDataReader, filling a datatable, trying to parse the result with ifs
string getMax = #"select COALESCE(MAX(IDCompany), 0) + 1 AS maxPlusOne
from Companii"
using(SqlConnection cnn = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand(getMax, cnn))
{
cnn.Open();
int nextCompanyID = Convert.ToInt32(cmd.ExecuteScalar());
}
The COALESCE function checks the result of the MAX function and if it is NULL returns the second parameter (here 0), then just increment by 1 to get the next MAX directly from the database. ExecuteScalar will do the call returning just the maxPlusOne alias field
try this snippet:
Convert Your String into Int. String with + operator will con-cat and with int it will add numbers.
if (idmax.Rows[0][0].ToString().Trim() == "") { txtID.Text = "1"; }
else {
txtID.Text = Convert.ToString(Convert.ToInt32(idmax.Rows[0][0] .ToString())+1); }
Try This one, my id format is USR001.The code will generate auto id based on the last id inside the database. If the last id in the database is USR001, the the code will generate USR002 and put the id to the textbox
con.Open();
string sqlQuery = "SELECT TOP 1 kode_user from USERADM order by kode_user desc";
SqlCommand cmd = new SqlCommand(sqlQuery, con);
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
string input = dr["kode_user"].ToString();
string angka = input.Substring(input.Length - Math.Min(3, input.Length));
int number = Convert.ToInt32(angka);
number += 1;
string str = number.ToString("D3");
txtKodeUser.Text = "USR" + str;
}
con.Close();

Login page in asp.net. Issue with query?

I would like to create a simple login page in asp.net. here is my code:
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=TEST-PC\\SQLSERVER2012;Initial Catalog=oncf;Integrated Security=True";
conn.Open();
string query = "SELECT COUNT(*) FROM Account WHERE acc_username= '" + TextBox1.Text + "' AND acc_password= '" + TextBox2.Text + "'";
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataReader myreader = cmd.ExecuteReader();
int count = 0;
while(myreader.Read())
{
count = count + 1;
}
if(count==1)
{
Response.Redirect("page2.aspx");
}
else
{
Label1.Visible = true;
}
conn.Close();
}
I set a counter in order to know if the credentials entered are present in the DB. If the value of the counter goes to 1, the login is successful. Otherwise, the label with a message error is displayed!
However, whatever I enter as input in the username and login textboxes, it always redirect me to the other page !
For now, my concern is not the security aspects, I just want to test this simple code, I don't see any problem with the code, but still it doesnt work, it is driving me crazy...
The reason that you are always redirecting is that your reader always returns 1 row, whether there is a match or not. If there is a match in your database, then the query will return
(no column name)
---------------
1
If there is not a match then it will return:
(no column name)
---------------
0
Either way, myreader.Read() will return true, and you will increment count in this part:
while(myreader.Read())
{
count = count + 1;
}
if(count==1)
{
Response.Redirect("page2.aspx");
}
Rather than checking the if the query returns rows you can retrieve the value of the count using SqlCommand.ExecuteScalar(). In addition to this I would make three more changes:
1. Use parameterised queries
This is not just a security concern, parameterised queries are able to use cached plans, whereas if you concatenate the parameters into the query then a new plan is compliled for each new variable value. In addition, parameterised queries are more strongly typed, and you don't need to escape things like O'shea to ensure that your extra quote doesn't mess up the query.
2. Encrypt the passwords
This is directly to do with security so should really be overlooked as per your request to not comment on security, HOWEVER, this answer is not just for your benefit, and a half answer is likely to be read by someone in the future who may or may not be aware of the risks of storing plain text passwords. There is a simple encryption method in this answer.
3. Add using blocks to your code
A minor change, but when you have objects that implement IDisposable it is a good idea to use a using block to esnure they are disposed of properly.
So you might end up with:
string password = SomeStaticClass.Encrypt(TextBox2.Text);
string connectionString = "Data Source=TEST-PC\\SQLSERVER2012;Initial Catalog=oncf;Integrated Security=True";
string query = "SELECT UserCount = COUNT(*) FROM Account WHERE acc_username= #UserName AND acc_password= #Password";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
connection.Open();
command.Parameters.Add("#UserName", SqlDbType.VarChar, 50).Value = TextBox1.Text;
command.Parameters.Add("#Password", SqlDbType.VarChar, 50).Value = password;
int count = Convert.ToInt32(command.ExecuteScalar());
if(count==1)
{
Response.Redirect("page2.aspx");
}
else
{
Label1.Visible = true;
}
}
The problem you are experiencing is because the followinq query Always returns one row even if there isn't a match in the database:
SELECT COUNT(*) FROM Account WHERE acc_username=....
If there is no match, you get a row with one column, value 0.
You are checking the number of rows returned when you should just be checking the return value.
Use this instead
int count = Convert.ToInt32(cmd.ExecuteScalar());
if(count==1)
{
Response.Redirect("page2.aspx");
}
else
{
Label1.Visible = true;
}
I know you said you don't want advice on security but just to be sure:
Don't store passwords plain text in a database. Always hash them using a salt.
Don't use string concatenation when building sql. Use parameters.
don't use ExecuteReader when you want to return a single value, use ExecuteScalar:
int count = int.Pares(cmd.ExecuteScalar().toString());
if(count >= 1)
{
Response.Redirect("page2.aspx");
}
else
{
Label1.Visible = true;
}
You should always use Paremeterized queries Using parameters in SQL statements
string username=TextBox1.Text;
string password=TextBox2.Text;
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=TEST-PC\\SQLSERVER2012;Initial Catalog=oncf;Integrated Security=True";
conn.Open();
SqlCommand cmd = new SqlCommand("SELECT * FROM Account WHERE acc_username=#username and
AND acc_password=#password", conn);
cmd.Parameters.AddWithValue("#username",username);
cmd.Parameters.AddWithValue("#password",password);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
Response.Redirect("page2.aspx");
}
else
{
Label1.Visible = true;
}
Try adding if (myreader.HasRows) before while(myreader.Read())

How can I get the result of a stored procedure in C#?

Here is my code in C#:
float r_discountValue = 0;
SqlConnection con = Constant.GetConnection();
SqlCommand cmd = new SqlCommand("Coupon_GetDiscountFromValidCouponCode", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#PKCouponCode", SqlDbType.VarChar);
cmd.Parameters["#PKCouponCode"].Value = "DIS_77";
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
if(reader.Read()){
r_discountValue = float.Parse(reader[0].ToString());
}
reader.Close();
}
catch(Exception exception)
{
throw exception;
}
finally{
con.Close();
}
return r_discountValue;
The stored procedure:
ALTER PROCEDURE [dbo].[Coupon_GetDiscountFromValidCouponCode]
#PKCouponCode varchar(50)
AS
SELECT *
FROM Coupon
WHERE CouponCode = #PKCouponCode AND Valid = 1
Here is how the DB looks like:
I encounter an error
Input string was not in a correct format
I don't know what's thing is going wrong, any ideas?
If you want the discount value, then you should return only the discount from the SP (since it is named GetDiscountfrom...)
SELECT CouponDiscount FROM Coupon WHERE CouponCode = #PKCouponCode AND Valid = 1
This will make it a one-column resultset, which matches the access reader[0] from C#.
The other option is of course to change the C# side to read the second item (index 1) or reference the column by name, e.g.
r_discountValue = float.Parse(reader[1].ToString());
r_discountValue = float.Parse(reader["CouponDiscount"].ToString());
You would have got Input string was not in a correct format. because it was reading "DIS_77" which float.parse cannot process.
You are using first column i.e.CouponCode for fetching discount. instead of that you need to use second column ie. couponDiscount
So try something like this
r_discountValue = float.Parse(reader["CouponDiscount"].ToString());

extracting data from data set

Respected Users,
I am extracting data using data set.
I want to put value in textbox. But value is not comming.
I have following Code
try
{
da = new SqlDataAdapter("select ID from Customer where Name='" + gvBkPendingSearch.SelectedRows[0].Cells[1].Value.ToString() + "'",con);
DataSet ds = new DataSet();
da.Fill(ds);
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
txtCustomerID.Text = ds.Tables[0].Rows[0].ToString();
}
catch (Exception ex)
{
}
finally
{
}
txtCustomerID is my textbox.
It is capturing value as>>>>>System.Data.DataRow
Error is in txtCustomerID.Text = ds.Tables[0].Rows[0].ToString();
but i am not able to understand it.
Please help me.
change it like this
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
txtCustomerID.Text = ds.Tables[0].Rows[i]["ID"].ToString();
The mistake you are doing is, you are accessing this
ds.Tables[0].Rows[0].ToString();
means 0th row, the whole row!! not the column value
And the datatable row is System.Data.DataRow in .Net
You need to select the column:
txtCustomerID.Text = ds.Tables[0].Rows[i][0].ToString();
Also note that you are overwriting the value of the textbox on each iteration of the loop. So what you will end up with is the ID of the last record in this textbox.
Also your query seems vulnerable to SQL injection. Personally I would recommend you scraping the DataSets in favor of an ORM or even plain old ADO.NET:
public static IEnumerable<int> GetIds(string name)
{
using (var conn = new SqlConnection("Your connection string comes here"))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "select ID from Customer where Name=#Name";
cmd.Parameters.AddWithValue("#Name", name);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
yield return reader.GetInt32(reader.GetOrdinal("ID"));
}
}
}
}
And now you could happily use this function:
string name = gvBkPendingSearch.SelectedRows[0].Cells[1].Value.ToString();
int id = GetIds(name).FirstOrDefault();
txtCustomerID.Text = id.ToString();

Categories

Resources