Choose between two SQL statements using CASE or something else - asp.net

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
)

Related

Error: There is no row at position 0 in asp.net

I wrote this code to get data from gridview to display down the controls, but it failed:
There is no row at position 0.
at line:
txtSTT.Text = ds.Tables["Trailer"].Rows[0].ItemArray.GetValue(0).ToString();
Full code:
protected void btnSua_Click(object sender, EventArgs e)
{
string STT = ((LinkButton)sender).CommandArgument;
SqlConnection conn = new SqlConnection(#"Data Source=DESKTOP-R8LG380\SQLEXPRESS;Initial Catalog=PHIM;Integrated Security=True");
string query = "SELECT * FROM Trailer WHERE STT = '" + STT + "'";
SqlCommand cmd = new SqlCommand(query, conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds, "Trailer");
txtSTT.Text = ds.Tables["Trailer"].Rows[0].ItemArray.GetValue(0).ToString();
txtMaTrailer.Text = ds.Tables["Trailer"].Rows[0].ItemArray.GetValue(1).ToString();
cmbMaPhim.SelectedValue = ds.Tables["Trailer"].Rows[0].ItemArray.GetValue(2).ToString();
txtUrlTrailer.Text = ds.Tables["Trailer"].Rows[0].ItemArray.GetValue(3).ToString();
txtGhiChu.Text = ds.Tables["Trailer"].Rows[0].ItemArray.GetValue(4).ToString();
txtSTT.ReadOnly = true;
txtSTT.Visible = true;
lbSTT.Visible = true;
}
From the error message, I would say your query is not returning any rows.
Try putting a break point right after the assignment to the queryand copy the string into a query window in SQL Server Management Studio to see if any rows of data come back.
It is probably not returning any rows. Debug your query until you know you have one that returns data.
Also, In addition to putting the contents of this function in a try/catch block, I would wrap all the lines that use ds.Tables["Trailer"].Rows[0] in an if block, something like if(ds.Tables["Trailer"].Rows.Count > 0){

select as sql and use in 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.

asp SQL Statement to insert multiple rows of record into Table

I am trying to create an attendance table to record down the activities the students have participated. The code below is triggered when a new activity is created. When a new activity is created, I want to insert all the student record into attendance table and mark the default attend attribute as false. (the attend attribute is to mark attendance, sets as 0)
The problem is that the attendance table cannot be populated. The code will stop proceeding at the line: numofRecordsAffected = command.ExecuteNonQuery();
I am trying to get the all the sigstudentid(s) from the Student table. I do not know if the usage of foreach() is recommended in this case, but any help will be appreciated.
I need a solution!
public int InsertAttendance(int num)
{
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand command = new SqlCommand();
SqlConnection connect = new SqlConnection();
DataSet dataset = new DataSet();
String sqlText = "SELECT * FROM Student";
connect.ConnectionString = "Data Source=TECKISTTLE; Initial Catalog=Assignment; Integrated Security=True";
command.Connection = connect;
command.CommandText = sqlText;
int numofRecordsAffected = 0;
adapter.SelectCommand = command;
connect.Open();
adapter.Fill(dataset, "StudentData");
sqlText = "";
foreach (DataRow item in dataset.Tables["StudentData"].Rows)
{
sqlText += " INSERT INTO Attendance(SIGStudentID, ActivityId, Attendance) VALUES(#SIGStudentID,#ActivityId,#Attendance); ";
command.Parameters.Clear();
command.Parameters.Add("#SIGStudentID", SqlDbType.Int);
command.Parameters["#SIGStudentID"].Value = Convert.ToInt32(item["SIGStudentID"]);
command.Parameters.Add("#ActivityId", SqlDbType.Int);
command.Parameters["#ActivityId"].Value = num;
command.Parameters.Add("#Attendance", SqlDbType.Bit);
command.Parameters["#Attendance"].Value = 0;
}
numofRecordsAffected = command.ExecuteNonQuery();
connect.Close();
return numofRecordsAffected;
}
As you put the code numofRecordsAffected = command.ExecuteNonQuery(); out side your foreach.
It just execute one time. As this code is actual statement to INSERT data in to the table, it will INSERT only one ROW the last one.
Just try to put your code
numofRecordsAffected = command.ExecuteNonQuery();
inside the foreach block. Then it will INSERT each row.
public int InsertAttendance(int num)
{
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand command = new SqlCommand();
SqlConnection connect = new SqlConnection();
DataSet dataset = new DataSet();
String sqlText = "SELECT * FROM Student";
connect.ConnectionString = "Data Source=TECKISTTLE; Initial Catalog=Assignment; Integrated Security=True";
command.Connection = connect;
command.CommandText = sqlText;
int numofRecordsAffected = 0;
adapter.SelectCommand = command;
connect.Open();
adapter.Fill(dataset, "StudentData");
sqlText = "";
numofRecordsAffected = 0;
sqlText = "INSERT INTO Attendance(SIGStudentID, ActivityId, Attendance) VALUES(#SIGStudentID,#ActivityId,#Attendance); ";
command.CommandText = sqlText;
foreach (DataRow item in dataset.Tables["StudentData"].Rows)
{
command.Parameters.Clear();
command.Parameters.AddWithValue("#SIGStudentID", Convert.ToInt32(item["SIGStudentID"]);
command.Parameters.AddWithValue("#ActivityId", num);
command.Parameters.AddWithValue("#Attendance", 0);
numofRecordsAffected += command.ExecuteNonQuery();
}
connect.Close();
return numofRecordsAffected;
}
You're probably over complicating it a bit by using a loop and could do something like this instead:
"INSERT INTO Attendance(SIGStudentID, ActivityId, Attendance) select SIGStudentID, " + num + " as ActivityId, 0 as Attendance from Student;"
Reference:
insert one column data from a table into other table, but the other column data will be specified dynamically
Insert all values of a table into another table in SQL

i want to use data reader & update statement at same time

here is code
String[] month=new String[12]{"January","February","March","April","May","June","July","August","September","Octomber","November","December"};
int day = DateTime.Now.Day;
int mon= DateTime.Now.Month;
mon = mon - 1; //because month array is with 0
Label1.Text = day.ToString();
if (day==21)
{
int j = 1;
SqlCommand cmd1 = new SqlCommand();
cmd1.Connection = MyConn;
cmd1.CommandText = "SELECT No_of_times,Dustbin_no from mounthly_data";
SqlDataReader MyReader = cmd1.ExecuteReader();
while (MyReader.Read())
{
String a = MyReader["No_of_times"].ToString();
String b = MyReader["Dustbin_no"].ToString();
SqlCommand cmd = new SqlCommand();
cmd.Connection = MyConn;
cmd.CommandText = "update Yearly_data set [" + month[mon] + "]='"+a+"' where Dustbin_no='"+b+"'"; //just see ["+month[mon+"] it's imp
i = cmd.ExecuteNonQuery();
}
MyReader.Close();
}
i got error as
There is already an open DataReader associated with this Command which must be closed first.
I think you should give us the rest of the code above this code block because I'm not sure how a ExecuteNonQuery is using up a datareader. But from what I can gather, what you probably want is to open two separate connections. Only one datareader can be open per connection at a time. Either you use two separate connections or you could maybe use a datatable/dataset for the result of both your queries.
EDIT: From the rest of your code, yes, using two connections would be the simplest answer. When a reader is open, the connection associated with it is dedicated to the command that is used, thus no other command can use that connection.
I would recommend using a DataTable as this OLEDB example shows:
public static void TrySomethingLikeThis()
{
try
{
using (OleDbConnection con = new OleDbConnection())
{
con.ConnectionString = Users.GetConnectionString();
con.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM Customers";
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
foreach (DataRow row in dt.AsEnumerable())
{
cmd.CommandText = "UPDATE Customers SET CustomerName='Ronnie' WHERE ID = 4";
cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}

How can I execute multiple database requests in ASP.NET C#?

In every ASP.NET application I have written, I would make number of request to the database before outputting the information onto the web page.
For example:
var DataTable1 = GetDataTable("Select * From Customers");
var DataTable2 = GetDataTable("Select * From Products");
var DataTable3 = GetDataTable("Select * From Orders");
As far as I'm aware, the code above would make 3 separate trips to the database and would do them one after the other.
Is there anyway I can gather together my parameterized SQL statements and make only 1 trip to the database server?
var SqlString = "SELECT * FROM Customers; SELECT * FROM Products; SELECT * FROM ORDERS;");
var ds = GetDataSet(SqlString);
var DataTable1 = ds.Tables(0);
var DataTable2 = ds.Tables(1);
var DataTable3 = ds.Tables(2);
My solution:
SqlConnection con = new SqlConnection("Server=CLASS-III-WKS10\\SQLEXPRESS;Initial
Catalog=wind;Integrated Security=True");
int[] id=new int[9];
int i = 0;
page_load()
{
con.Open();
SqlCommand cmd = new SqlCommand("select *from windmill", con);
SqlDataReader rd = cmd.ExecuteReader();
while (rd.Read())
{
id[i] = rd.GetInt32(9);
i++;
//MessageBox.Show(id.ToString());
}
rd.close();
SqlCommand cmd1 = new SqlCommand("Update windmill set State='Stopped',PmState='Not Available'where Id=0", con);
cmd1.ExecuteNonQuery();
}
Use semi-colons to separate SQL statements and reader.NextResult to get each set. Your code will end up looking something like this.
Using con As New SqlConnection
Using cmd As New SqlCommand("Select * From Customers; Select * From Products; Select * From Orders")
Using reader = cmd.ExecuteReader
Dim dt1 As DataTable
dt1.Load(reader)
reader.NextResult()
Dim dt2 As DataTable
dt2.Load(reader)
reader.NextResult()
Dim dt3 As DataTable
dt3.Load(reader)
End Using
End Using
End Using
Create a Thread class and place a method in that class which accept string query as input:
then create a Thread object and start the object.
Check this out http://msdn.microsoft.com/en-us/library/aa645740(VS.71).aspx

Resources