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

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

Related

SqlDataReader with two tables

I have a very simple code which fetches data from two tables
Inventory
Category
and displays them in two different GridView controls using SqlDataReader in the Page_Load event of an ASP.NET web application.
My point is, shouldn't SqlDataReader automatically traverse to the next table (Category) after reading the data from the previous table (Inventory)? Instead of using NextResult(), if I had reused the rdr object again for the next grid i.e. CategoryGridView without executing NextResult(), I'd get nothing (meaning it has moved on from Inventory?!)
So in a nutshell my question is where is the rdr pointing towards after reading from the first table (Inventory)?
using (SqlConnection con = new SqlConnection(CS))
{
SqlCommand cmd = new SqlCommand("Select * from tblInventory; Select * from tblCategory", con);
con.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
InventoryGridView.DataSource = rdr;
InventoryGridView.DataBind();
rdr.NextResult();
CategoryGridView.DataSource = rdr;
CategoryGridView.DataBind();
}
}
connection.Open();
SqlCommand command = new SqlCommand("Select * from tblInventory; Select * from tblCategory", connection);
using (SqlDataReader reader = command.ExecuteReader())
{
InventoryGridView.DataSource = reader;
InventoryGridView.DataBind();
while (reader.NextResult())
{
CategoryGridView.DataSource = reader;
CategoryGridView.DataBind();
}
}

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.

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
)

Detailsview in ASP.NET

I am trying to hit sql server with objectdatasource and return a datatable to fill my details view control. the selected ID value is returned by a gridview control. It seems like the datatable is not filled by adapter, and i couldn't figure out why. The ID in sql is set as a primary key (Int, 4, not null). The debugger says the Detail datatable is null. Any help is much appreciated.
public DataTable GetDetail(string ID)
{
if (ID == "")
{
return null;
}
else
{
DataTable Detail = null;
using (SqlConnection conn = new SqlConnection(connection))
{
string comm = #"select * from dbo.Products where ID = #ID";
conn.Open();
SqlDataAdapter adapter=null;
using (SqlCommand cmd = new SqlCommand(comm, conn))
{
cmd.Parameters.Add("ID", System.Data.SqlDbType.Int, 4).Value = Convert.ToInt32(ID);
adapter = new SqlDataAdapter(cmd);
adapter.Fill(Detail);
return Detail;
}
}
}
I think you missed the commandType
cmd.CommandType = CommandType.Text;
Try this
DataSet ds = new DataSet();
using (SqlConnection con = new SqlConnection(connection))
{
string myquery="select * from dbo.Products where ID = #ID";
SqlCommand cmd = new SqlCommand(myquery, con);
SqlDataAdapter dap = new SqlDataAdapter();
dap.SelectCommand = cmd;
cmd.Parameters.Add("#ID", SqlDbType.NVarChar, 15).Value = ID;
dap.Fill(ds);
return ds.Tables[0];
}
Thanks for ALL.
The problem is I didnt initialize my datatable to a new instance.
DataTable Detail = null; ===> DataTable Detail = new Datatable();
and also the convert should be done in sql not in codes.
cmd.Parameters.Add("ID", System.Data.SqlDbType.Int, 4).Value = ID;
string comm = #"select * from dbo.Products where ID = convert(int,#ID)";

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);
}
}

Resources