I am getting error in this line
account = int.Parse(cmd.ExecuteScalar().ToString());// ERROR
every time i am trying to run this program . Its gives me same error.The Account number is an integer and the value is coming from text box1.and the account holder name comes from text box2. this is an SQL transaction method . when i clicked the button the out put i am expecting to increase the balance or reduce the balance. this is the thing i am trying to do. I am not very expert i am trying to learn .Please replay me so i can correct this error.Thnaks
Here is my C# code . But when i run this application its shows following errors.Input stream not in correct format
namespace BANKINHNTIRE1
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int account = System.Convert.ToInt32(textBox1.Text);
string sql = "select statementamount from ACCOUNT WHERE Account_Number ='" + textBox1.Text + "'";
SqlConnection cn = new SqlConnection(#"Data Source=KHUNDOKARNIRJOR\KHUNDOKERNIRJOR;Initial Catalog=Login;Integrated Security=True");
SqlCommand cmd = new SqlCommand(sql, cn);
cn.Open();
account = int.Parse(cmd.ExecuteScalar().ToString());
if (account > 0)
{
int j;
SqlTransaction trans;
SqlCommand cmd1 = new SqlCommand();
trans = cn.BeginTransaction();
cmd1.Connection = cn;
cmd1.Transaction = trans;
cmd1.CommandType = CommandType.Text;
cmd1.CommandText = "update ACCOUNT set statementamount=statementamount+'" + textBox3.Text + "' where Account_Number ='" + textBox1.Text + "' and First_Name='" + textBox2.Text + "'";
j = cmd1.ExecuteNonQuery();
if (j == 1)
{
trans.Commit();
MessageBox.Show("credited...");
}
else
trans.Rollback();
}
else
{
MessageBox.Show("u can't make credit...");
}
}
}
}
The first thing I'd check is why you trying to convert a statementamount (almost certainly a floating point value) with int.parse().
You're also placing it into the variable account despite the fact it's not an account number, so it may be that you've mistakenly conflated account and amount, in which case it's probably better as:
double amount = Double.Parse(cmd.ExecuteScalar().ToString());
if (amount > 0) ...
In any case, you really should catch exceptions if you can recover from them, and this is certainly a case where you can do so (by, for example, putting up an error dialog then not trying to process the transaction further).
Beyond that, you can break down the statement into components so you can identify where the problem occurs more specifically:
object obj = cmd.ExecuteScalar();
string str = obj.ToString();
account = int.Parse(str);
Single-stepping through that and examining the variables should hopefully make it clear what the actual problem is.
int.Parse will throw an exception if the input cannot be parsed into an integer. You should only use this method if you are sure that the input looks like a number. I would guess that your select statement is returning nothing which causes the error.
You should use int.TryParse() instead which will return true if the parse worked. Some sample code would be
string input = cmd.ExecuteScalar().ToString();
int value;
bool success = int.TryParse(input, out value);
if (success)
{
//use the value
}
Have you tried int.tryparse? Or have you check whether cmd.ExecuteScalar Return a null value. You haven't provide the exact error so I'm just guessing. Try this:
int num1 = 0;
//Check whether cm.ExecuteScalar was null, if yes then use empty string
var sqlResult = cmd.ExecuteScalar() ?? "";
//Next Try parse it to int, if it failed then return 0, you may also return null to determine that you have no records at all.
account = int.TryParse(sqlResult .ToString(), out num1) ? num1 : 0;
You should use int.Parse() or you can put it under try{} catch{} to validate the values passed.
int account = 0;
try
{
account = int.Parse(textBox1.Text.Trim());
}
catch(Exemption emp)
{
account=0; // or any default value
MessageBox.Show(emp.Message);
}
And also, you can check it line by line by adding breakpoint on account. And debug it by pressing F11.
Related
I want to shift some variables by one. I searched for the command for it but I couldn't find. If anybody knows it please help me.
Here is the code:
private int shiftNumbers(int number)
{
int newNumber = 0;
string stm = "UPDATE devices SET number= #newNumber WHERE number>#number";
try
{
con.Open();
cmd = new MySqlCommand(stm, con);
cmd.Parameters.AddWithValue("#number", number);
}
catch (Exception e)
{
ErrorMessage = e.Message;
con.Close();
return null;
}
try
{
rdr = cmd.ExecuteReader();
while(rdr.Read()) {
newNumber = rdr.GetInt32(1);
cmd.Parameters.AddWithValue("#newNumber ", (newNumber-1));
}
}
catch (Exception e)
{
ErrorMessage = e.Message;
con.Close();
return null;
}
con.Close();
return 1;
}
I know this code useless but I show it for you to get the logic that I want to do.
I think your approach is wrong.
First, you read from the database, using a select statement;
Then you go over that result, your rdr.Read();
Then you create a new command, updating the original record;
Move forward in your reader (rdr) and repeat from 2 until you are done.
What you are doing now is impossible. You can't get a result set from an update, just a count affected.
Or, if you can, let your update statement do the calculation (it seems it is only subtracting one from the original number, so why not do that in SQL?):
string stm = "UPDATE devices SET number = number - 1 WHERE number>#number";
Yes, your code is really useless. In your update statement you are passing a parameter #newNumber bu not providing it. Closing the connection in catch block.
string stm = "UPDATE devices SET number= #newNumber WHERE number>#number";
First decide from where you are going to get the #newNumber value and then add that as parameter and use ExecuteNonQuery() method.
If you want pass the other parameter as well in your method and use it like
private int shiftNumbers(int number, int newNumber)
{
//int newNumber = 0;
string stm = "UPDATE devices SET number= #newNumber WHERE number>#number";
using(SqlConnection con = new SqlConnection(connectionString))
{
cmd = new MySqlCommand(stm, con);
SqlParameter paramNumber = new SqlParameter("#number", SqlDbType.Int);
paramNumber.Value = number;
SqlParameter paramNewNumber = new SqlParameter("#newNumber", SqlDbType.Int);
paramNewNumber.Value = newNumber;
cmd.Parameters.Add(paramNumber);
cmd.Parameters.Add(paramNewNumber);
con.Open();
cmd.ExecuteNonQuery();
}
//Rest of your code logic if any
}
I've created a website that is connected to the database, I can get data and display it on the page with no prob at all. But when I try to insert (or update) it does nothing.
I have tested the SQL query and it works just fine.
I've looked here for similar situations and questions here for the past 24 hours with no luck.
I want the website to tell if the user want a one way or two way tickets and make a request. The table has the request id which is automatically incremented
then I add the id of the student who is requesting, the the id of the departure ticket then the id of return ticket (if it is 2 ways, this value can be null) there is also status which will be pending until a supervisor either accept or decline the request, once accepted, issue date will be added and status will change to approved. If declined reason will be added and status change to declined.
Main issue, when I make the request, the row is not created and added to the database for the supervisor to view later.
Here is my code:
protected void Button1_Click(object sender, EventArgs e)
{
int parsedValue;
int.TryParse(DropDownList1.SelectedValue, out parsedValue);
SqlConnection myConnection = new SqlConnection(""); // I removed the connection string.
string sqlcommand = "";
string idString = TextBox1.Text;
string idTwoString ="";
bool canContune = false;
if (parsedValue == 1)
{
System.Diagnostics.Debug.WriteLine("p");
Panel3.Visible = true;
idTwoString = TextBox2.Text;
if (AllNumber(idString, TextBox1) && AllNumber(idTwoString, TextBox2))
{
canContune = true;
}
}
else if (AllNumber(idString, TextBox1))
{
canContune = true;
}
if (canContune)
{
int dId;
int dId2;
int.TryParse(idString, out dId);
int.TryParse(idTwoString, out dId2);
sqlcommand = "INSERT INTO TicketRequest.dbo.TicketRequest (student_id, departure_id, return_id, statues, issue_date, notes) "
+ "VALUES (#student_id, #departure_id , #return_id , #statues, #issue_date, #notes)";
try
{
SqlCommand cmd = new SqlCommand(sqlcommand);
cmd.CommandType = CommandType.Text;
cmd.Connection = myConnection;
myConnection.Open();
cmd.Parameters.Add("#student_id", SqlDbType.Int).Value = id;
cmd.Parameters.Add("departure_id", SqlDbType.Int).Value = dId; //I used AddWithValue(#para, value) it didn't work.
if (parsedValue == 0)
{
cmd.Parameters.AddWithValue("#return_id", DBNull.Value);
}
else
{
cmd.Parameters.Add("#return_id", SqlDbType.Int).Value = dId2;
}
cmd.Parameters.Add("#statues", SqlDbType.Text).Value = "Pending";
cmd.Parameters.AddWithValue("#issue_date", DBNull.Value);
cmd.Parameters.AddWithValue("#notes", DBNull.Value);
cmd.ExecuteNonQuery();
myConnection.Close();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
}`
It doesn't throw any exception, I really don't know what is wrong.
I would be very thankful to anyone who will point me out my mistake in Insert query. Thanks in advance.
==================================================
I apologized all, it worked just fine. it seemed that the code wasn't excuted to being with. Thanks Falanor, you helped me discover the problem. =)
Try to check the return value.
int modified =(int)cmd.ExecuteScalar();
This is also missing the # symbol for the parameter
cmd.Parameters.Add("departure_id", SqlDbType.Int).Value = dId; //I used AddWithValue(#para, value) it didn't work.
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();
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())
I am generating a random number admission no and this is my DAL
public static int randomgen()
{
int id=0;
int number = r.Next(100);
HttpContext.Current.Session["number"] = "SN" + (" ") + number.ToString();
SqlConnection con = DBConnection.OpenConnection();
try
{
string sql1 = "select admissionno from tblstudent_details";
SqlCommand cmd=new SqlCommand(sql1,con);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
id = Convert.ToInt32(dr[0]);
}
dr.Close();
return id;
}
catch (Exception)
{
throw;
}
}
and i am checking if there is any duplicate is getting generated but i am getting an error like Input string is not in a correct format?Where i am doing wrong?Is any better way than this?
You asked if there is a better way...
From what I understand about the question what you are trying to do is pick a random value and then check the database to see if that value already exists. You want to return a value back to the UI to tell the UI whether the value exists or not...
Here is a couple alternatives to consider...
public static bool randomgen()
{
bool isFound = false;
string admissionNumber = "SN " + r.Next(100);
HttpContext.Current.Session["number"] = admissionNumber;
using (SqlConnection con = new SqlConnection()) // use "using" to guarantee connection is closed
{
string sql1 = "SELECT CASE WHEN EXISTS(SELECT admissionno FROM tlblstudent_details WHERE admissionno = #admissionno) THEN 1 ELSE 0 END";
using (SqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("#admissionno", number);
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
isFound = (Convert.ToInt32(dr[0]) == 1)
}
}
}
}
return isFound;
}
This way you let SQL Server check to see if the value exists.
Another approach...
Not sure if you are required to prompt the user if the value is not unique, if that is not a requirement then I would consider a different approach; Keep trying until you find a unique value...Like this...
public static int randomgen()
{
bool isFound = true;
while (isFound)
{
string admissionNumber = "SN " + r.Next(100);
using (SqlConnection con = new SqlConnection()) // use "using" to guarantee connection is closed
{
string sql1 = "SELECT CASE WHEN EXISTS(SELECT admissionno FROM tlblstudent_details WHERE admissionno = #admissionno) THEN 1 ELSE 0 END";
using (SqlCommand cmd = con.CreateCommand(sql1))
{
cmd.Parameters.AddWithValue("#admissionno", admissionNumber);
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
isFound = (Convert.ToInt32(dr[0]) == 1)
}
}
}
}
return number;
}
This keeps checking until a unique value is returned. Then you return that unique value to the calling method. Now you set HttpContent.Current session from the caller, leaving the responsibility of this method to only be finding a unique Admission Number. The downside to the second approach is that it may take a long time to find a unique value, depending on how many values are already used, especially considering you are only allowing 100 values.
Hope this gives you good alternatives to consider. Let me know if you have additional questions.