I am using a SQLDataReader to read a limited number of rows from a table so that I can page them into a gridview. Once I have read the number of rows I want, I want to exit; however the Reader.Close (or Reader.Dispose) does not return immediately.
I am doing this to show comparisons of various ways of reading data, so I am not looking for alternative solutions. I simply want to exit the code when I have the desired number of rows.
Here is the code:
SqlDataReader Reader = null;
SqlConnection Connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ZipData"].ConnectionString);
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("ZipCode", System.Type.GetType("System.String")));
dt.Columns.Add(new DataColumn("City", System.Type.GetType("System.String")));
dt.Columns.Add(new DataColumn("State", System.Type.GetType("System.String")));
try
{
string Query = string.Format("{0} WHERE ZipCode Like #ZipCode AND City Like #City AND State Like #State ORDER BY {1}", SQLQuery, (string.IsNullOrEmpty(sortType)) ? "ZipCode" : sortType);
SqlCommand Command = new SqlCommand(Query, Connection);
Command.Parameters.Add(new SqlParameter("#ZipCode", filter.Zip + "%"));
Command.Parameters.Add(new SqlParameter("#City", filter.City + "%"));
Command.Parameters.Add(new SqlParameter("#State", filter.State + "%"));
Connection.Open();
Reader = Command.ExecuteReader();
int CurrentRow = 0;
DataRow row;
while (Reader.Read())
{
if (CurrentRow >= startRowIndex)
{
if (dt.Rows.Count > maximumRows) break;
row = dt.NewRow();
row["ZipCode"] = (string)Reader["ZipCode"];
row["City"] = (string)Reader["City"];
row["State"] = (string)Reader["State"];
dt.Rows.Add(row);
}
CurrentRow++;
}
Reader.Close();
}
catch (SqlException ex)
{
ErrorMessage = ex.Message;
}
finally
{
Connection.Close();
}
return dt;
After looking at Microsoft's documentation, you can speed up closing the connection by cancelling the sql command.
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.close.aspx
So, you should be able to add this prior to closing to achieve your desired outcome.
Command.Cancel()
I know you didn't want alternate solutions, but why not use SELECT TOP 200 or whatever maximumRows is in the SQL? This would improve just about everything; less load on SQL Server, network, and local computer...
After testing your code, I didn't see a problem with closing the reader nor connection. Can you better describe the issue?
Related
I have a table in my database and two textbox and a button in my ASP.NET. I want to call database and select product name and code and if the entrance is correct I want to ok message, otherwise false!
Here is my code, but I did not get correct result.
try
{
string constring = System.Configuration.ConfigurationManager.ConnectionStrings["WebDataBaseConnectionString"].ConnectionString;
SqlConnection scon = new SqlConnection(constring);
scon.Open();
SqlCommand cmd = new SqlCommand("select * from Product where Name=#Name and Code=#Code", scon);
cmd.Parameters.AddWithValue("#Name", txtName.Text);
cmd.Parameters.AddWithValue("#Code", txtCode.Text);
SqlDataReader dr = cmd.ExecuteReader();
scon.Close();
Label1.Text = "The Product is in our list.Thank you";
}
catch(Exception)
{
Label1.Text = "The Product is not in our list.Sorry!";
}
Your query is modified as below
try
{
string constring = System.Configuration.ConfigurationManager.ConnectionStrings["WebDataBaseConnectionString"].ConnectionString;
SqlConnection scon = new SqlConnection(constring);
scon.Open();
SqlCommand cmd = new SqlCommand("select * from Product where Name=#Name and Code=#Code", scon);
cmd.Parameters.Add("#Name", SqlDbType.Varchar).Value = txtName.Text;--Update the datatype as per your table
cmd.Parameters.Add("#Code", SqlDbType.Varchar).Value = txtCode.Text;--Update the datatype as per your table
SqlDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
--If you want to check the whether your query has returned something or not then below statement should be ommitted. Else you can check for a specific value while reader is reading from the dataset.
while (dr.Read())
{
--The returned data may be an enumerable list or if you are checking for the rows the read statement may be ommitted.
--To get the data from the reader you can specify the column name.
--for example
--Label1.Text=dr["somecolumnname"].ToString();
Label1.Text = "The Product is in our list.Thank you";
}
}
else
{
Label1.Text = "The Product is not in our list.Sorry!";
}
scon.Close();
}
catch (Exception)
{
Label1.Text = "The Product is not in our list.Sorry!";
}
Hope this answer will help you in resolving your query.
I am trying to simply read data from my SQL Server database and input them into text fields on a webform.
I can't figure out what I'm missing but everything compiles smoothly and runs but my text fields remain empty.
protected void Page_Load(object sender, EventArgs e)
{
String index = Request.Form["indexTb"];
string constr = ConfigurationManager.ConnectionStrings["TravelLogConnectionString2"].ConnectionString;
SqlConnection con = new SqlConnection(constr);
string selectSql = "SELECT Location, Date, Message FROM EntryLogs WHERE ID='" + Convert.ToInt32(index) + "'";
SqlCommand com = new SqlCommand(selectSql, con);
try
{
con.Open();
using (SqlDataReader reader2 = com.ExecuteReader())
{
while (reader2.Read())
{
reader2.Read();
LocTb.Text = (reader2["Location"].ToString());
DateTb.Text = (reader2["Date"].ToString());
MessTb.Text = (reader2["Message"].ToString());
}
reader2.Close();
reader2.Dispose();
}
}
finally
{
con.Close();
}
}
You're calling the reader2.Read(); twice - once in the while loop, once just below:
while (reader2.Read())
{
reader2.Read(); // <=== WHY call .Read() a second time ?!?!!?!
LocTb.Text = (reader2["Location"].ToString());
DateTb.Text = (reader2["Date"].ToString());
MessTb.Text = (reader2["Message"].ToString());
}
That's both unnecessary, and could lead to no results being returned.
If your query only returns one row, the .Read() in the while loop would read that row and return it, but then the next line does another Read(), which would not return any data (since the first and only row has already been read).
Just remove that unnecessary second call to .Read() and I bet your data will begin to show up!
And to fix that glaring SQL injection - use parametrized queries! as one should always do anyway!
string selectSql = "SELECT Location, Date, Message FROM EntryLogs WHERE ID = #Id;";
SqlCommand com = new SqlCommand(selectSql, con);
com.Parameters.Add("#Id", SqlDbType.Int).Value = Convert.ToInt32(index);
try
{
con.Open();
using (SqlDataReader reader2 = com.ExecuteReader())
{
while (reader2.Read())
{
// REMOVE THIS reader2.Read();
LocTb.Text = (reader2["Location"].ToString());
DateTb.Text = (reader2["Date"].ToString());
MessTb.Text = (reader2["Message"].ToString());
}
reader2.Close();
reader2.Dispose();
}
}
finally
{
con.Close();
}
protected void Button1_Click(object sender, EventArgs e)
{
string db = "Data Source=DESKTOP-R6H3RTP;Initial Catalog=AdmitDB; Integrated Security= true;";
SqlConnection mycon = new SqlConnection(db);
mycon.Open();
String query = "select * from tblPatient where PhoneNo like '"+TextBox1.Text+"%'";
SqlCommand cmd = new SqlCommand(query, mycon);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
if (cmd.ExecuteNonQuery() > 0)
{
lblName.Visible = true;
lblId.Visible = true;
lblPNo.Visible = true;
lblDOB.Visible = true;
lblName.Text = "PName";
lblId.Text = "Pid";
lblPNo.Text = "PhoneNo";
lblDOB.Text = "PDOB";
}
else
{
lblNotFound.Visible = true;
}
}
i'm searching from database but just else statement executes don't know why it's not get data from database, if any kind of error then help me please
i think you don't need if (cmd.ExecuteNonQuery() > 0). the cmd executes automatically. you want to check the tables in the dataset.
// check the first table for rows.
if(ds.Tables[0].HasRows())
{
// success. now you can work with the table.
}
ExecuteNonQuery method returns the number of row that were modified by the query. Since SELECT query doesn't modify anything in the database - you get 0.
You should modify your query with a COUNT(*) function:
String query = "select COUNT(*) from tblPatient where PhoneNo like '"+TextBox1.Text+"%'";
Then you can get that value with ExecuteScalar():
if (cmd.ExecuteScalar() > 0)
I am getting an error "must declare scalar variable #IdAlbum". I have already been through similar posts on this topic but it does not help. Can someone have a look at the code below? When i use command paramters it gives me error. If I do not use command parameters, it works fine. I have put comments in the code to highlight where the problem is.
public DataSet databind ()
{
DataSet ds = new DataSet();
string con_str = ConfigurationManager.ConnectionStrings["con_nc"].ConnectionString;
SqlConnection con = new SqlConnection(con_str);
try
{
con.Open();
string albumId = Request.QueryString["AlbumId"].Trim();
this.albumName = Request.QueryString["AlbumName"];
//getting the count of the pictures from DB and assigning it to pagesize so that all pictures of single album come in 1 page only.
string photoCountQuery = "select count(*) from gallery_photos where AlbumId=#albumId"; // THIS WORKS FINE
SqlCommand picCount = new SqlCommand(photoCountQuery, con);// THIS WORKS FINE
picCount.Parameters.AddWithValue("#albumID", albumId);// THIS WORKS FINE
int photoCount = Convert.ToInt16(picCount.ExecuteScalar());// THIS WORKS FINE
int start = (int)ViewState["start"];// THIS WORKS FINE
ViewState["pagesize"] = photoCount;// THIS WORKS FINE
//string query = "select * from gallery_photos where AlbumId='" + albumId + "'"; //// THIS WORKS FINE
string query = "select * from gallery_photos where AlbumId=#IdAlbum";// THIS is the problem. It does not work when i use command paramters
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue("#IdAlbum", albumId);
SqlDataAdapter da = new SqlDataAdapter(query, con);
da.Fill(ds, start, (int)(ViewState["pagesize"]), "gallery_photos");
}
catch (Exception ex)
{
ExceptionUtility.LogException(ex, "Exception in " + Path.GetFileName(Page.AppRelativeVirtualPath).ToString());
Context.ApplicationInstance.CompleteRequest();
}
finally
{
con.Close();
}
return ds;
}
Look at this: https://msdn.microsoft.com/en-us/library/ebxy9a8b(v=vs.80).aspx
You are doing it wrong, you should use DataAdapter to fill missing parameters.
Look also at this question and answer, it provides good explanation: c# Using Parameters.AddWithValue in SqlDataAdapter
I have the following code:
using (SqlConnection cn = new SqlConnection(Connection.Instance.ConnectionString))
{
// Open the connection
using (SqlCommand cmd = new SqlCommand())
{
try
{
cmd.Connection = cn;
cmd.CommandText = "Select Customers.CustomerID, Addresses.AddressCode, Addresses.FirstName, Addresses.LastName, Addresses.Address1, Addresses.City, Addresses.State, " +
"Addresses.Zip, Addresses.Home AS HomePhone, Addresses.Phone AS WorkPhone, Addresses.EmailAddress From Customers " +
"LEFT OUTER JOIN Addresses ON Addresses.ID=Customers.AddressID " +
"Where CustomerType IN ('HomeOwner', 'Home Owner') AND Customers.ResellerID=#ResellerID ";
cmd.Parameters.AddWithValue("#ResellerID", base.UserID);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet dsCustomer = new DataSet();
da.Fill(dsCustomer);
var customers = from c in dsCustomer.Tables[0].AsEnumerable().AsQueryable()
where c.Field<string>("CustomerID") == txtSearchCriteria.Text
select c;
dgCustomers.CurrentPageIndex = 0;
dgCustomers.DataSource = customers;
dgCustomers.DataBind();
}
catch (Exception e)
{
throw new Exception(e.Message + e.StackTrace);
}
finally
{
if ((cn != null) && (cn.State != ConnectionState.Closed))
cn.Close();
}
}
}
Which is giving me the error
AllowCustomPaging must be true and VirtualItemCount must be set for a DataGrid with ID 'dgCustomers' when AllowPaging is set to true and the selected data source does not implement ICollection. at System.Web.UI.WebControls.DataGrid.CreateControlHierarchy(Boolean useDataSource)
How do I convert this LINQ query so that it can be pagable?
Note: This is a simplified version of what I'm trying to do. I know in this example I could simply modify the SQL statement to include "And CustomerID=#CustomerID" and bypass LINQ completely. But, in the bigger picture, I can't do that.
The error message is clear, you need to implement your paging logic to take advantage from paging. BTW, to make your code to work just use a ICollection as DataSource, changing this line:
dgCustomers.DataSource = customers.ToList();