Insert data into database in ASP.NET throwing exception - asp.net

I'm trying to insert data into database in ASP.NET with this code:
string conn = "TJLDatabaseConnectionString";
conn = ConfigurationManager.ConnectionStrings["Conn"].ToString();
SqlConnection objsqlconn = new SqlConnection(conn);
objsqlconn.Open();
SqlCommand objcmd = new SqlCommand("Insert into MeterReading(MachineName,LastReading,CurrentReading,Consumption) Values('" + TextBox1.Text + "','" + TextBox2.Text + "','" + TextBox3.Text + "','" + TextBox4.Text + "')", objsqlconn);
objcmd.ExecuteNonQuery();
//MessageBox.Show("Successful");
But when I run it. It gives the following message:

First the important, always use sql-parameters to prevent sql-injection. Never concatenate parameters into a sql-query. This can also solve localization or "escaping" issues.
Also, use the using statement to ensure that anything using unmanaged resources (like a sql-connection) will be closed and disposed even on error:
string sql = #"
INSERT INTO MeterReading(MachineName,LastReading,CurrentReading,Consumption)
VALUES(#MachineName,#LastReading,#CurrentReading,#Consumption)";
using(var objsqlconn = new SqlConnection(ConfigurationManager.ConnectionStrings["Conn"].ToString()))
using (var cmd = new SqlCommand(sql, objsqlconn))
{
cmd.Parameters.AddWithValue("#MachineName", TextBox1.Text);
cmd.Parameters.AddWithValue("#LastReading", TextBox2.Text);
cmd.Parameters.AddWithValue("#CurrentReading", TextBox3.Text);
cmd.Parameters.AddWithValue("#Consumption", TextBox4.Text);
objsqlconn.Open();
int insertedCount = cmd.ExecuteNonQuery();
}
Side-note: if you have an identity column and you want to retrieve the newly created primary-key, use SCOPE_IDENTITY and ExecuteScalar even if you use INSERT INTO:
string sql = #"
INSERT INTO MeterReading(MachineName,LastReading,CurrentReading,Consumption)
VALUES(#MachineName,#LastReading,#CurrentReading,#Consumption);
SELECT CAST(scope_identity() AS int)";
//...
int newID = (int)cmd.ExecuteScalar();

Use a variable to check if row is getting affected or not
rowAffected= objcmd.ExecuteNonQuery();
if(rowAffected >0)
{
//sucessful
}
else
{
//
}

Since there is no any exception mention in your question so just for a better and readable code I would suggest you too use using blocks. It gives you nice, cleaner and readable code and also handle objects when they go out of scope.
This is meant for good practices that we generlly follow while coding. Kindly show us the exception for appropriate solution.
private void ConnectToDb()
{
var conn = ConfigurationManager.ConnectionStrings["Conn"].ConnectionString;
using( var conn = new SqlConnection(conn))
{
conn.Open();
var cmdtxt ="Insert into MeterReading(MachineName,LastReading,CurrentReading,Consumption)
Values(#P1,#P2,#P3,#P4)";
using(var cmd = new SqlCommand(cmdtxt, conn))
{
cmd.CommandType=CommandType.Text;
cmd.Parameters.AddWithValue("#P1", TextBox1.Text);
cmd.Parameters.AddWithValue("#P2", TextBox2.Text);
cmd.Parameters.AddWithValue("#P3", TextBox3.Text);
cmd.Parameters.AddWithValue("#P4", TextBox4.Text);
cmd.ExecuteNonQuery();
}
con.close();
}
}

Related

Getting error from accessing DataReader value (accessing joined table results in SqlDataReader)

UPDATE - PROBLEM SOLVED
Just in case to retrieve all data at once, using a single SQL statement to retrieve joined table results, but couldn't access it and received error below
Exception details: System.IndexOutOfRangeException: crsName
By the way, anyone please suggest a more convenient way to deal with a GridView that need to display a JOIN result.
Instead of this approach - https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.datacontrolfieldcollection.add?view=netframework-4.8
BoundField courseBF = new BoundField();
courseBF.DataField="courseName";
courseBF.HeaderText="Course Name";
//Which is stated in Microsoft Document
Here's the code receive error
string userID = (string)Session["userID"];
string sql = "SELECT courseID from gpaSem where stuID=#userID";
string temp = "";
string temp02 = "";
string[] crsID;
string[] crsName;
string[] grade;
SqlConnection con = new SqlConnection(cs);
SqlCommand cmd = new SqlCommand(sql, con);
cmd.Parameters.AddWithValue("#userID", userID);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
temp += ("!" + dr["courseID"]);
}
crsID = temp.Split('!');
crsID = crsID.Skip(1).ToArray();//course ID get
dr.Close();
con.Close();
con.Open();
temp = "";
foreach (string crs in crsID)
{
sql = "SELECT G.grade AS grade, C.crsName AS crsName FROM gpaSem G, course C WHERE G.courseID=C.courseID AND G.courseID=#courseID";
cmd.Parameters.AddWithValue("#courseID", crs);
dr = cmd.ExecuteReader();
if(dr.Read())
{
temp += "!" + dr["crsName"];//error
temp02 += "!" + dr["grade"];
}
}
crsName = temp.Split('!');
crsName = crsName.Skip(1).ToArray();//course name get
grade = temp02.Split('!');
grade = grade.Skip(1).ToArray();//grade get
dr.Close();
con.Close();
My point is, is that I should explicitly use JOIN in SQL statement or the way I access the value is wrong?

How to managed two sql queries in ASP.Net (Visual Studio 2010)

So what I'm trying to do is once I click a button. I want one sql query to insert values to the "Return_Process" Table and another sql query to delete data from the matching loan ID in another table, which is "Loan_Process".
This is the code I have written but its not deleting anything, its inserting the values to the return process but not deleting it from the loan process.
//Global variable declaration
string path;
string sql;
string sql2;
//create a method for database connection
public void connection()
{
//connection string
path = #"Data Source=NATHAN-PC\SQLEXPRESS;Initial Catalog=ASP;Integrated Security=True";
}
protected void Button1_Click(object sender, EventArgs e)
{
{
connection();
SqlConnection con = new SqlConnection(path);
con.Open();
//try
{
sql = "INSERT INTO Return_Process (Return_ID, FIne, Actual_Returned_Date, Loan_ID) VALUES ('" + txtRID.Text + "','" + txtfine.Text + "','" + TextBox1.Text + "','" + txtLID.Text + "')";
sql2 = "Delete FROM Loan_Process WHERE Loan_ID='"+txtLID+"'";
SqlCommand cmd = new SqlCommand(sql, con);
cmd.ExecuteNonQuery();
//lblerrormsg.Visible = true;
//lblerrormsg.Text = "Success";
con.Close();
//GridView1.DataBind();
}
//catch (SqlException)
//{
// //lblerrormsg.Visible = true;
// //lblerrormsg.Text = "Invalid";
//}
con.Close();
//GridView1.DataBind();
}
}
}
}
I'm pretty bad at ASP.net, so if someone could tell me what to do to execute both queries at the same time, would greatly appreciate it.
Do something like this:
//your code
sql = "INSERT INTO Return_Process (Return_ID, FIne, Actual_Returned_Date, Loan_ID)"
+ " VALUES (#rid, #fine, #retDate, #lid); " //note ; inside
+ "Delete FROM Loan_Process WHERE Loan_ID=#lid;";
var cmd = new SqlCommand(sql, con);
cmd.Parameters.Add("#rid", SqlDbType.Int).Value = Int.Parse(txtRID.Text);
//similar for 3 remaining parameters. Just set correct SqlDbType
con.Open();
cmd.ExecuteNonQuery();
con.Close();

There is already an open DataReader associated with this Command which must be closed first.Why?

protected void Page_Load(object sender, EventArgs e)
{
MultiView1.ActiveViewIndex=0;
string str = "SELECT t1.UsrFLname from Registration t1 JOIN IMSLogin t2 on t1.RegId = t2.RegId and t2.Uname = '" + Login1.UserName + "'";
con.Open();
SqlCommand cmdr = new SqlCommand(str, con);
SqlDataReader dr = cmdr.ExecuteReader();
if (cmdr.ExecuteReader().HasRows)//here showing the error as the title i gave.
{
Session["userName"] = Login1.UserName.Trim();
string myStringVariable = "Welcome! ";
ClientScript.RegisterStartupScript(this.GetType(), "myAlert", "alert('" + myStringVariable + Login1.UserName + "');", true);
//dr.Dispose();
}
else
{
string myStringVariable = " No Username Found";
ClientScript.RegisterStartupScript(this.GetType(), "myAlert", "alert('" + myStringVariable + "');", true);
}
con.Close();
}
I used datareader object dr in the same page in other events too...
Plz help....
Why are you calling ExecuteReader two times? One is enough
SqlDataReader dr = cmdr.ExecuteReader();
if (dr.HasRows)
{
-----
Your code has also other problems. Sql Injection is the most Dangerous. You should use code like this when passing values entered by your user
string str = "SELECT t1.UsrFLname from Registration t1 JOIN IMSLogin t2 on " +
"t1.RegId = t2.RegId and t2.Uname = #uname";
con.Open();
SqlCommand cmdr = new SqlCommand(str, con);
cmdr.Parameters.AddWithValue("#uname", Login1.UserName);
SqlDataReader dr = cmdr.ExecuteReader();
and also using a global connection is a bad practice because you keep an expensive resource locked. Try to use the using statement, open the connection, the command and the reader and then close and destroy everything
// CREATE CONNECTION AND COMMAND
using(SqlConnection con = new SqlConnection(conString))
using(SqlCommand cmdr = new SqlCommand(str, con))
{
// OPEN THE CONNECTION
con.Open();
cmdr.Parameters.AddWithValue("#uname", Login1.UserName);
using(SqlDataReader dr = cmdr.ExecuteReader())
{
// USE
....
} // CLOSE AND DESTROY
} // CLOSE AND DESTROY
You've already opened the reader in the line above. I think you want:
SqlDataReader dr = cmdr.ExecuteReader();
if (dr.HasRows)//here showing the error as the title i gave.
But there are other issues - SQL Injection as #Brad M points out (do a search on parameterised queries), and you're leaking your command objects - they ought to be enclosed in using statements.
I'm also slightly nervous about what/where con is defined - it smells strongly like a global variable of some kind. The general pattern for using ADO.Net is to, inside a single method/block of code, you should create a new SqlConnection object (inside a using statement), create a new SqlCommand object (inside a using statement), open the connection, execute the command, process the results (if applicable) and then exit the using blocks and let everything get cleaned up. Don't try to share SqlConnection objects around.
you already execute reader on
SqlDataReader dr = cmdr.ExecuteReader();
So in if, you should use existing reader
dr.HasRows
Initialy be careful in your sql scripts
Avoid
string str = "SELECT t1.UsrFLname from Registration t1 JOIN IMSLogin t2 on t1.RegId = t2.RegId and t2.Uname = '" + Login1.UserName + "'";
Use
string str = "SELECT t1.UsrFLname from Registration t1 JOIN IMSLogin t2 on t1.RegId = t2.RegId and t2.Uname = #username";
con.Open();
SqlCommand cmdr = new SqlCommand(str, con);
cmdr.Parameters.AddWithValue("#username", Login1.UserName);
SqlDataReader dr = cmdr.ExecuteReader();
if (dr.HasRows)
{
Session["userName"] = Login1.UserName.Trim();
string myStringVariable = "Welcome! ";
ClientScript.RegisterStartupScript(this.GetType(), "myAlert", "alert('" + myStringVariable + Login1.UserName + "');", true);
}
and DO NOT forget to
dr.Close();

Insert current datetime based onclick

I am currently trying to store datetime in the database. The idea is when onclick on the button, the database will store the current datetime in the database.
I have tried some methods but they prompt me with this error:
"Incorrect syntax near '26/6/2013 00:00:00'"
This is my codes:
con.Open();
query = "INSERT INTO dbo.url_map (long_url, expiry_date) Values ('" + tbLongURL.Text + "' , '" + DateTime.Today + "')";
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#long_url", tbLongURL.Text);
cmd.Parameters.AddWithValue("#expiry_date", DateTime dt = DateTime.ParseExact(DateTime.Today.ToString(), "dd/MM/yyyy h:mm:ss tt", CultureInfo.InvariantCulture));
cmd.ExecuteNonQuery();
what is wrong with the way i add the date time?
Any help will be greatly appreciated.
Corrected query-
query = "INSERT INTO dbo.url_map (long_url, expiry_date) Values ('" + tbLongURL.Text + "', '" + DateTime.Today + "')";
If you use parameters I think your query should be
query = "INSERT INTO dbo.url_map (long_url, expiry_date) Values (#long_url, #expiry_date)";
//this way sqlcommand make sense
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#long_url", tbLongURL.Text);
cmd.Parameters.AddWithValue("#expiry_date", DateTime.Today);
protected void Button1_Click(object sender, EventArgs e)
{
Insert();
}
public void Insert()
{
try
{
_conn = new SqlConnection(con);
_cmd = new SqlCommand();
_cmd.Connection = _conn;
_conn.Open();
_cmd.CommandType = CommandType.StoredProcedure;
_cmd.CommandText = "insert_date";
_cmd.Parameters.Add("#Date",SqlDbType.DateTime).Value = DateTime.Now;
_cmd.ExecuteNonQuery();
_conn.Close();
}
catch (Exception ex)
{
}
}
Stored Procedure:
create procedure insert_date
#Date datetime
as
insert into DateTable values(#Date)
Result after insertion on table:
1 2013-06-26 14:29:36.987
You can directly bind the Current Date to 'expiry_date' column in SQL server.
Steps:
Right click on your table and select 'Design'.
Click on the desired column, 'expiry_date' in your case.
In the column property, look for 'Default Value or Binding' in General Section.
Put 'GETDATE()' as the default value, so whenever you insert the record, it will take current date as its value.

Need help reading multiple values back from sql server database in asp code

here is my codebehind for grabbing data from database:
public static string getTestimonial()
{
string username = "xxxxx";
SqlConnection Conn = new SqlConnection(ConfigurationManager.ConnectionStrings["xxxxxxx"].ConnectionString);
Conn.Open();
string sql = "select testimonial,submitname from (SELECT TOP 1 * FROM dbo.testimonials where username='" + username + "' ORDER BY newid()) as answer;";
SqlCommand cmd = new SqlCommand(sql, Conn);
string test=cmd.ExecuteScalar().ToString();
Conn.Close();
return test;
}
yet when I try to display the data on my aspx page all I get is the first value:
<div class="span3">
<%= getTestimonial() %>
</div>
can you please help me with a method of getting both the testimonial and the submitname from the query into variables?
Thanks!
Thanks! Solved! using:
public static string getTestimonial()
{
string username = "xxxxxx";
SqlConnection Conn = new SqlConnection(ConfigurationManager.ConnectionStrings["xxxxxxx"].ConnectionString);
Conn.Open();
string sql = "select testimonial,submitname from (SELECT TOP 1 * FROM dbo.testimonials where username='" + username + "' ORDER BY newid()) as answer;";
SqlCommand cmd = new SqlCommand(sql, Conn);
var test = new StringBuilder();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
test.Append(reader.GetString(0));
test.Append(" and ");
test.Append(reader.GetString(1));
}
}
Conn.Close();
return test.ToString();
}
ExecuteScalar() will always return first column of the first row - a single value. You may want to rethink your approach, meanwhile the simplest way is to make your query return combined value:
string sql = "select testimonial + ' and ' + submitname from ....
As an aside, you probably should rewrite that function to not use inline SQL, as you are making your site vulnerable to SQL injection attacks potentially in writing it this way. (presumably, userid is not set as a constant XXXXX in the actual function and is instead passed in somehow).

Resources