select as sql and use in asp.net - asp.net

i want select from my sql and create a session from one table field
string strquery = "select * from Registration where username=#username ";
SqlConnection connection2 = DBConnection.getConnection();
connection2.Open();
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = connection;
cmd2.CommandText = strquery;
cmd2.Parameters.Add("#username", txt1_username.Text);
SqlDataReader nwReader = cmd2.ExecuteReader();
string cus = "";
if (nwReader.Read())
{
cus = nwReader["customer_id"].ToString();
}
nwReader.Close();
connection.Close();
Session["customer_id_se"] = cus.ToString();
Response.Redirect("Wedding.aspx");
my problem is: i can't use that field and use in session

You are doing few mistakes, let me point them first(obviously it will solve the issue too).
As i mentioned in the comment, "you are creating connection2 and
opening connection using connection.Open(); it should be either
connection2.Open(); or remove connection2 from the block.
The .Parameters.Add() method expect SqlDbType specify them and add its value using the following statement.
cmd2.Parameters.Add("#username",SqlDbType.VarChar).Value = txt1_username.Text;
There may be situations where nwReader will not having any rows(query returns no result). Accessing value from it in such situation will give you exception as "Invalid attempt to read when no data is present", So you need to check for existence of data in the Reader before accessing it.
That is you should use like the following:
SqlDataReader nwReader = cmd2.ExecuteReader();
string customerId = String.Empty;
if (nwReader.HasRows)
{
customerId = nwReader["customer_id"].ToString();
}
4. customerId is already a string so you need not to convert it again using .ToString() before assigning to the session. So the complete scenario can be coded as like the following:
string strquery = "select * from Registration where username=#username";
SqlConnection connection = DBConnection.getConnection();
connection.Open();
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = connection;
cmd2.CommandText = strquery;
cmd2.Parameters.Add("#username", SqlDbType.VarChar).Value = txt1_username.Text;
SqlDataReader nwReader = cmd2.ExecuteReader();
string customerID = "";
if (nwReader.HasRows)
{
customerID = nwReader["customer_id"].ToString();
}
nwReader.Close();
connection.Close();
Session["customer_id_se"] = customerID;
Note :-
If nwReader.HasRows is false means there is no such record for the
specific username, in this case customerID and hence
Session["customer_id_se"] will be blank.
Updates as per HansKesting's comment,
Select * will fetch the entire rows which satisfies the condition in the Where clause. If you requires only a single value and you are sure that the result will be either empty or a single value then you can use SELECT column_name from ... and in such situations use ExecuteScalar to get the value.

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 get the Query String variable in ASP.NET and pass it as an Sql parameter?

string userid = Request.QueryString[0].ToString();
string Qid = Request.QueryString[1].ToString();
string connection = ConfigurationManager.ConnectionStrings["dbconnection"].ConnectionString.ToString();
SqlConnection con = new SqlConnection(connection);
con.Open();
SqlCommand com = new SqlCommand("qualification", con);
com.Parameters.Add("#proctype",SqlDbType.Int).Value = 4;
com.Parameters.Add("#Qid", SqlDbType.Int).Value = Qid;
SqlDataReader reader = com.ExecuteReader();
while (reader.Read())
{
drpqualification.SelectedItem.Text = reader["Qualification"].ToString();
txtSubjects.Text = reader["Subject"].ToString();
txtmarksobt.Text = reader["MarksObtained"].ToString();
txtgrade.Text = reader["Percentage"].ToString();
txtboard.Text = reader["BoardUniversity"].ToString();
}
reader.Close();
con.Close();
}
and here the URL:http://localhost:35689/Academic_info.aspx?userid=94&Qid=14
i want to get the Qid only and pass it as Sql Parameter*
You should add values to parameters as below -
command.Parameters.Add("#ID", SqlDbType.Int);
command.Parameters["#ID"].Value = customerID;
// Use AddWithValue to assign Demographics.
// SQL Server will implicitly convert strings into XML.
command.Parameters.AddWithValue("#demographics", demoXml);
Check this URL - https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.parameters(v=vs.110).aspx
And to fetch the query string, just use Request.QueryString["Qid"]. You don't need to .ToString() it.

I need to loop for all records in table in my database

I need to loop for all records in my table , cose here is not working properly in my project "Auction web system" , I use web service here to check the status of product Periodically , and when the status is opened and data time is less to now , update the
product and set its status to "closed".
the code here work only for one row at the time !
I need to check for all rows at the same time.
{
string sql12 = "SELECT item_id FROM items Where status='opened' AND endDate<=#endate ";
SqlCommand cmd12 = new SqlCommand(sql12, con);
con.Open();
cmd12.Parameters.AddWithValue("#endate", DateTime.Now);
query = Convert.ToInt32(cmd12.ExecuteScalar());
string sql123 = "UPDATE items SET status ='closed' WHERE item_id =#Item_ID";
SqlCommand cmd21 = new SqlCommand(sql123, con);
cmd21.Parameters.AddWithValue("#Item_ID", query);
cmd21.ExecuteNonQuery();
con.Close();
CalculateWinningPrice(query);
}
public void CalculateWinningPrice(Int32 query)
{
string sql1 = "SELECT MAX(Bid_price) AS Expr1 FROM Bid WHERE (item_id = #Item_ID)";
SqlCommand cmd1 = new SqlCommand(sql1, con);
con.Open();
cmd1.Parameters.AddWithValue("#Item_ID", query);
Int32 max = Convert.ToInt32(cmd1.ExecuteScalar());
SqlCommand cmd3 = new SqlCommand("SELECT user_id FROM Bid WHERE(Bid_price =(SELECT MAX(Bid_price) AS Expr1 FROM Bid AS BID_1 WHERE(item_id = #Item_ID)))", con);
cmd3.Parameters.AddWithValue("#Item_ID", query);
Int32 winner = Convert.ToInt32(cmd3.ExecuteScalar());
SqlCommand cmd4 = new SqlCommand("SELECT name FROM items WHERE (item_id=#Item_ID)",con);
cmd4.Parameters.AddWithValue("Item_ID", query);
string product_name = Convert.ToString(cmd4.ExecuteScalar());
GeneratePDF.create_pdf(product_name, Convert.ToDecimal(max).ToString("c"), DateTime.Now.ToString());
SqlCommand cmd = new SqlCommand("INSERT INTO Winners VALUES(#item_id, #user_id,#win_price,#win_date)");
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#item_id", query);
cmd.Parameters.AddWithValue("#user_id", winner);
cmd.Parameters.AddWithValue("#win_price", max);
cmd.Parameters.AddWithValue("#win_date", DateTime.Now);
cmd.Connection = con;
cmd.ExecuteNonQuery();
con.Close();
}
You can just use one update statement to update all the items status to 'colesed' where the enddate is passed. This is only if you don't need the item_id somewhere else.
So your code above can be;
string sql123 = "UPDATE items SET status ='closed' Where status='opened' AND endDate<=GETDATE()";
SqlCommand cmd21 = new SqlCommand(sql123, con);
cmd21.ExecuteNonQuery();
con.Close();
You can combine both queries into one query and update directly as follows:
Update items
Set status = 'closed'
Where status='opened'
AND endDate<=#endate
Then pass the required value as parameter and run the query with ExecuteNonQuery method.

Choose between two SQL statements using CASE or something else

I have a dropdown and I want to check the selected value first before I run my SQL command so here is my logic: if the selected value of the dropdown is not 'ALL' then I want to run this sql statement:
select distinct Location
from myTable
where PROGRAM = '"+program+'"
else if selected value of the dropdown is set to 'ALL' then I want to run this SQL command instead:
select distinct Location
from myTable
Here is my my code which works fine but not the way I want it to work. How can I modify the SQL command so I can check the condition that I mentioned above? Thanks
protected void BindServiceList(DropDownList ddlService)
{
DropDownList ddl = (DropDownList)GV_MJJ.HeaderRow.FindControl("ddlProgram");
string program = ddl.SelectedValue;
String strConnString = System.Configuration.ConfigurationManager
.ConnectionStrings["myConn"].ConnectionString;
SqlConnection con = new SqlConnection(strConnString);
SqlDataAdapter sda = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand("select distinct LOCATION" +
" from myTable where PROGRAM = '" + program + "' ");
cmd.Connection = con;
con.Open();
ddlService.DataSource = cmd.ExecuteReader();
ddlService.DataTextField = "LOCATION";
ddlService.DataValueField = "LOCATION";
ddlService.DataBind();
con.Close();
ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
.Selected = true;
}
Don't change your SQL command instead create different SQL command's text based on the condition. Also you should use SqlParameter instead of string concatenation. Your code is prone to SQL injection. Consider enclosing your connection and command object in using statement as that will ensure resource disposal at the end of block.
using (SqlConnection con = new SqlConnection(strConnString))
{
SqlDataAdapter sda = new SqlDataAdapter();
using (SqlCommand cmd = new SqlCommand())
{
if (program.Equals("All", StringComparison.InvariantCultureIgnoreCase))
{
cmd.CommandText = "select distinct LOCATION from myTable";
}
else
{
cmd.CommandText = "select distinct LOCATION from myTable WHERE PROGRAM = #program";
cmd.Parameters.AddWithValue("#program", program);
}
cmd.Connection = con;
con.Open();
ddlService.DataSource = cmd.ExecuteReader();
ddlService.DataTextField = "LOCATION";
ddlService.DataValueField = "LOCATION";
ddlService.DataBind();
con.Close(); // can be left out because of `using` statement
ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
.Selected = true;
}
}
Do this:
protected void BindServiceList(DropDownList ddlService)
{
DropDownList ddl = (DropDownList)GV_MJJ.HeaderRow.FindControl("ddlProgram");
string program = ddl.SelectedValue;
String strConnString = System.Configuration.ConfigurationManager
.ConnectionStrings["myConn"].ConnectionString;
using (var con = new SqlConnection(strConnString) )
using (var cmd = new SqlCommand("select distinct LOCATION from myTable where PROGRAM LIKE #Program", con) )
{
//guessing at column type/length here
cmd.Parameters.Add("#Program", SqlDbType.NVarChar, 20).Value = program;
con.Open();
ddlService.DataSource = cmd.ExecuteReader();
ddlService.DataTextField = "LOCATION";
ddlService.DataValueField = "LOCATION";
ddlService.DataBind();
}
ddlService.Items.FindByValue(ViewState["Filter_Serv"].ToString())
.Selected = true;
}
Notice that I fixed your sql injection vulnerability! Also notice that I changed the = to a LIKE. Then you can set the value property for the All item in the ddlProgram control to: %. (See the AppendDataBoundItems property if you need help getting that working with a databound ddl). Using that wildcard with the LIKE operator will result in the query returning all locations.
Firstly Parameterize your query.
Since there are already solutions using c#. I will propose a SQL solution.
You could do a Case in your WHERE CLause by passing a parameter that suggests if the dropdown value is ALL.
Something like:
SELECT DISTINCT Location
FROM myTable
WHERE (
CASE
WHEN #IsAllSelected = 0
THEN PROGRAM
WHEN #IsAllSelected = 1
THEN 1
END
) = (
CASE
WHEN #IsAllSelected = 0
THEN #Your_program_value
WHEN #IsAllSelected = 1
THEN 1
END
)

Return a string Value from SQL Server stored procedure

I have the following method and stored procedure.
My question is how to return a string value from stored procedure to use in addStaffName method ?
public string addStaffName()
{
string staffName = string.Empty;
string sConnectionString = ConfigurationManager.ConnectionStrings["LGDB"].ToString();
SqlConnection SqlCOn = new SqlConnection(sConnectionString);
SqlCommand SqlCmd = new SqlCommand();
SqlCOn.Open();
SqlCmd.Connection = SqlCOn;
SqlCmd.CommandType = CommandType.StoredProcedure;
SqlCmd.CommandText = "FetchStaffName";
SqlCmd.Parameters.AddWithValue("email", email);
//???
return staffName;
}
create procedure fetchStaffName
#email varchar(100)
AS
begin
select (employeeName)
from employee
where email = #email
end
If you can be sure that you'llonly ever get one row, one column as a result set - then you can use .ExecuteScalar() on your SqlCommand like this:
string staffName = string.Empty;
string sConnectionString = ConfigurationManager.ConnectionStrings["LGDB"].ToString();
using (SqlConnection sqlCon = new SqlConnection(sConnectionString))
using (SqlCommand sqlCmd = new SqlCommand("FetchStaffName", sqlCon)
{
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.Parameters.AddWithValue("#email", email);
sqlCon.Open();
staffName = sqlCmd.ExecuteScalar().ToString();
sqlCon.Close();
return staffName;
}
I also put the usage of SqlConnection and SqlCommand into using() { ... } blocks which is the recommended best practice for anything that's deriving from IDisposable to ensure proper disposal of the objects after their use
Consider to make fetchStaffName a scalar function rather than stored procedure. By definition stored procedures are required to perform a set of actions with data. Scalar function guarantees there will be exactly one output value for the set of input values.
CREATE FUNCTION fetchStaffName (
#email VARCHAR(100)
)
RETURNS VARCHAR(?) --Place the length of employeeName field instead of ? symbol.
BEGIN
RETURN (SELECT employeeName FROM employee WHERE email = #email)
END
And then your .NET code transforms into the following:
using (SqlConnection SqlCOn = new SqlConnection(sConnectionString))
{
SqlCommand SqlCmd = new SqlCommand("SELECT fetchStaffName(#email)", SqlCOn);
SqlCmd.CommandType = CommandType.Text;
SqlCmd.Parameters.AddWithValue("#email", email);
SqlCOn.Open();
staffName = (string)SqlCmd.ExecuteScalar();
}
As you can see CommandType changed from StoredProcedure to Text. I also wrapped the work with SqlConnection object into using construction to dispose its resources and close automatically.

Resources