How to use multiple SqlDataReader in ASP.NET - asp.net

I use SqlDataReader connection1 inside that I use another SqlDataReader connection2. So connection open issue occurring connection1 open. How to resolve it? Kindly provide a solution

First create different connection, datareader... object
and close the connection datareader if data not read
example code
string connectionString1 = "Data Source=localhost;Integrated security=SSPI;Initial Catalog=AdventureWorks;";
string connectionString2 = "Data Source=localhost;Integrated security=SSPI;Initial Catalog=AdventureWorks;";
//Create the command
string sqlSelect1 = "SELECT TOP 5 CustomerID, AccountNumber FROM Sales.Customer";
string sqlSelect2 = "SELECT TOP 5 CustomerID, AccountNumber FROM Sales.Customer";
//open the connection
SqlConnection objConn1 = new SqlConnection(connectionString1);
SqlConnection objConn2 = new SqlConnection(connectionString2);
// Create the command and open the connection
SqlCommand objcommand1 = new SqlCommand(sqlSelect1, objConn1);
SqlCommand objcommand2 = new SqlCommand(sqlSelect2, objConn2);
objConn1.Open();
objConn2.Open();
// Create the DataReader to retrieve data
SqlDataReader DR1 = objcommand1.ExecuteReader())
SqlDataReader DR2 = objcommand2.ExecuteReader())
while (DR1.Read())
{
if(DR2.Read())
{
//YOUR CODE
}
else
{
DR2.Close();
}
}
DR1.Close();
DR2.Close();
objConn1.Close();
objConn2.Close();

Related

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.

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.

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

Invalid attempt to call Read when reader is closed

I'm kind of struggling trying to get this datagrid to bind. Everytime I run my code, I get an error message stating, "Invalid attempt to call Read when reader is closed". I don't see where I am closing my reader. Can you please help me? My code for loading the datagrid is below:
protected void LoadGrid()
{
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["VTC"].ConnectionString;
conn.Open();
string sql = "select * from roi_tracking";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
using (SqlDataReader sqlReader = cmd.ExecuteReader())
{
gridROI.DataSource = sqlReader;
gridROI.DataBind();
sqlReader.Dispose();
cmd.Dispose();
}
}
}
}
You can't use a SqlDataReader as a DataSource for a DataGrid.
From MSDN:
A data source must be a collection that implements either the
System.Collections.IEnumerable interface (such as
System.Data.DataView, System.Collections.ArrayList, or
System.Collections.Generic.List(Of T)) or the IListSource interface to
bind to a control derived from the BaseDataList class.
Datasource property:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.basedatalist.datasource.aspx
SqlDataReader:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.aspx
A common methodology to bind the query results to your datagrid would be to use a SqlDataAdapter to fill a DataTable or DataSet and then bind that to your DataGrid.DataSource:
protected void LoadGrid()
{
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["VTC"].ConnectionString;
conn.Open();
string sql = "select * from roi_tracking";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
adapter.Fill((DataTable)results);
gridROI.DataSource = results;
}
}
}
In addition to what pseudocoder said, you wouldn't want to bind to a SqlDataReader anyway: the connection to the database will remain open so long as the reader instance exists.
You definitely want to deserialize the data into some other disconnected data structure so that you release the connection back into the pool as quickly as possible.

Calling a stored procedure with asp.net

If I have a connection string defined in my web.config file, how do I create a connection to the SQL db from C# code (sorry forgot to specify) and then call a stored procedure. I would then like to eventually use this data in some way as my DataSource for a GridView.
Here is how the connection string is defined in the web.config:
<connectionStrings>
<add name="db.Name" connectionString="Data Source=db;Initial Catalog=dbCat;User ID=userId;Password=userPass;" providerName="System.Data.SqlClient" />
</connectionStrings>
The db server is a Microsoft SQL server.
Here is what I was looking for:
ConnectionStringSettings conSet = ConfigurationManager.ConnectionStrings["db.Name"];
SqlConnection con = new SqlConnection(conSet.ConnectionString);
The code to get the data is fairly trivial. I was more interested in accessing it from a connectionString variable in the web.config file.
If it's a resource file like so:
private static readonly string connString = Resource1.connString;
Where connString is the name of the key. If it is a web.config file
Something like so:
private static readonly string connString = System.Configuration.ConfigurationManager.AppSettings["strConn"]; where conn is defined in your web config file.
<add key="strConn" value="User ID=test;Password=test;Initial Catalog=TestDB;Data Source=NameOfServer;"/>
Then call the sproc:
//connString = the string of our database app found in the resource file
using (SqlConnection con = new SqlConnection(connString))
{
using (SqlCommand cmd = new SqlCommand("EMPDLL_selClientByClientID", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ClientID", SqlDbType.VarChar).Value = cID;
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
if (reader.Read())
{
//more code
}
}
}
}
}
That's if you are coding in C#, VB.net its the same deal just a bit more wordier :), here's a small sample:
Public Sub DeleteEmployee(ByVal lVID As Long)
Dim conMyData As SqlConnection
Dim cmdDelete As SqlCommand
Try
conMyData = New SqlConnection(connString)
cmdDelete = New SqlCommand("delEmployee", conMyData)
With cmdDelete
.CommandType = CommandType.StoredProcedure
'add the parameters
.Parameters.Add("#LoginID", SqlDbType.BigInt).Value = lVID 'the request
conMyData.Open() 'open a connection
.ExecuteNonQuery() 'execute it
End With
Catch ex As Exception
Throw ex
Finally
cmdDelete = Nothing
conMyData.Close()
conMyData = Nothing
End Try
End Sub
Of course you should use a using statement instead of try/catch/finally to ensure you clean up your resources that are being used.
Something like this...
using (var con = new SqlConnection(_connectionString))
{
using (var cmd = new SqlCommand(_storedProcedureName, con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#pMyParamater", myParamaterValue);
con.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// do something with the row
}
}
}
}
This is all pretty simple stuff to be honest, you should be able to find everything you need from the ADO.NET documentation

Resources