How to handle multiple rows scenario in SqlDataReader? - c#

I have a SQL query which supposed to return only ONE row from the business database. Based on this, I have written following sql script to get the data from the result set.
string query = #"select
ProdMaster.data_Id Id,
ProdMaster.data_name Name,
ProdMaster.data_countryname CountryName
from RM.Db
order by ProdMaster.data.FromDate desc"
SqlCommand command = new SqlCommand(query, conn);
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
countryname = reader["CountryName"].ToString();
}
}
But, there is some data issue in the database, sometimes it returns multiple rows.
How do we check the row count? If rows more than one we want to return a custom exception.
Note:
I do not want to use COUNT(*) in the query.
We don't have control on RM.Db database - it might have data issues (3rd party)

Don't you consider the next approach to solve your problem:
SqlCommand command = new SqlCommand(query, conn);
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
countryname = reader["CountryName"].ToString();
}
// Try to read the second row.
if (reader.Read())
{
// If we are inside this if-statement then it means that the query has returned more than one row.
// Here a custom exception must be thrown.
}
}

You can use SqlDataAdapter instead and fill the contents from the table in a dataset. The dataset will have a table inside it you can count the row like this - ds.Tables[0].Rows.Count
There can be problems related to Datareader as it is a stream of data and db can have changes while reading. A more thorough discussion on the same can be found on this thread -
How to get number of rows using SqlDataReader in C#

Related

How to read SQL Server COUNT from SqlDataReader

I'm trying to find the count for a table using C# SqlDataReader but I keep getting
invalid attempt to read when no data is present
My code:
string sql = "SELECT COUNT(*) FROM [DB].[dbo].[myTable]";
SqlCommand cmd = new SqlComman(sql, connectionString);
SqlDataReader mySqlDataReader = cmd.ExecuteReader();
int count = mySqlDataReader.GetInt32(0); // Here is where I get the error.
I know I have a valid connection to the database because I can read and write to it in many places, what's special about the COUNT(*) that I cannot read it properly? How do I get the int count to be populated?
You have to read it:
if (mySqlDataReader.Read()) {
count = mySqlDataReader.GetInt32(0);
}
Alternatively, you can just use ExecuteScalar:
int count = (int)cmd.ExecuteScalar();
which is defined as:
Executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored.
ExecuteScalar is what you require.

How To fetch all rows of a table from SQL database using SQL query in C#

I have a Grid View in which there is a Date column. In database I have one unique id column and a Date column. I want to get all the ids from the SQL query so that I can get all the ids for a particular date.
For example if I write "27-06-2013" then all ids 121,123,124 receive. When I am doing using Response.Write I am getting only a single id.
and all the ids then I want to show in grid view.
SqlCommand cmd = new SqlCommand("Select * from Scheduleappointment where Doctor_Id=#docid and Convert(varchar(5),Start_Time,108)+'-'+Convert(varchar(5),End_Time,108)=#time and Date=#date", con);
cmd.Parameters.AddWithValue("#docid", Label1.Text);
cmd.Parameters.AddWithValue("#time", timing.Text);
cmd.Parameters.AddWithValue("#date", Convert.ToDateTime(txtdate.Text).ToString("yyyy-MM-dd"));
conopen();
cmd.ExecuteNonQuery();
SqlDataReader dr = cmd.ExecuteReader();
if (dr.Read())
{
Response.Write(dr["Id"].ToString());
}
I want to show these id values in single row of grid view.Like 121,123 in single row next to date 27-06-2013.
The issue is with the last part
if (dr.Read())
{
Response.Write(dr["Id"].ToString());
}
The if will evaluate and read only once. If there is at least one row, it will be written. You probably need while, to read until there are no more rows.
while (dr.Read())
{
Response.Write(dr["Id"].ToString());
}
You will probably also want to add some formatting (spaces or line breaks between values) as well as clean up code (close the data reader, etc.) after writing.

Using Retrieved Data from a Parameterized SQL Query

If I'm using a parameterized query (ASP.NET with C#) in SQL, such as
var db = Database.Open("Database1");
SqlCommand cmd = new SqlCommand("SELECT * FROM pageinfo WHERE pageID = #pageID");
cmd.Parameters.AddWithValue("#pageID", 1);
And later on in the page, I want to do a foreach loop of whatever data was retrieved:
foreach(var row in ???)
What would I use (in place of the ???) to access the data I just retrieved?
Thanks.
It depends on how you execute a query.
Usually it's done by SqlCommand.ExecuteReader
For example, in your case, you can:
....
SqlDataReader reader = cmd .ExecuteReader();
while (reader.Read())
{
...
}
But there are also other ways to rertieve the data, for example using DataSet
For a complete example on how to do that can have a look on:
Using ADO.NET for beginners
You can use while iteration statement with SqlCommand.ExecuteReader instead of foreach. Take a look this;
var db = Database.Open("Database1");
SqlCommand cmd = new SqlCommand("SELECT * FROM pageinfo WHERE pageID = #pageID");
cmd.Parameters.AddWithValue("#pageID", 1);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader[0]);
}
reader[0] returns first row of first column and reader[1] returns first row of second column if your data has of course.

SQL Command not filling data reader

I am working on a nested repeater. My issue seems to be at the moment, that when I execute my SQL command that no data is returned to the data reader. Even when I run the exact same query (Copy and Pasted) into SQL Server.
My noteDrClient reader does not contain data, it does however know that there are 5 columns in the table. I have no idea what to do at this point or why no data is being passed into the data reader. Can anyone see an obvious problem?
SqlConnection con = new SqlConnection("Data Source=***;Initial Catalog=*;User ID=*;Password=*;Integrated Security=False;MultipleActiveResultSets=true;");
Above is my connection string. Please notice that I have Multiple Active Result Sets set to true. I did this because I kept getting errors about my data reader being open, even though it was closed.
protected void rptList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
if ((item.ItemType == ListItemType.Item) ||
(item.ItemType == ListItemType.AlternatingItem))
{
System.Data.Common.DbDataRecord rd = (System.Data.Common.DbDataRecord)e.Item.DataItem;
Repeater nestedRepeater = e.Item.FindControl("NotesRepeater") as Repeater;
string FID = rd[0].ToString();
using (cmd2 = new SqlCommand("SELECT * FROM notes WHERE FID = 1356;", con)) ;
SqlDataReader noteDrClient = cmd2.ExecuteReader(); //no data is being filled to the data reader... even though this command pulls data in SQL Server Management Studio.
if (noteDrClient.Read()) { //bind the repeater if there is data to bind
nestedRepeater.DataSource = noteDrClient;
nestedRepeater.DataBind();
}
noteDrClient.Close();
}
You're using statement is disposing the SqlCommand before you have a chance to use it. Additionally, you're attempting to bind to a DataReader. Get the results from the data reader into a collection of "Note" entities and bind to the collection instead.
using (SqlCommand cmd2 = new SqlCommand("SELECT * FROM notes WHERE FID = 1356;", con))
{
using(SqlDataReader noteDrClient = cmd2.ExecuteReader())
{
while (noteDrClient.Read())
{
Note n = new Note();
... get note from data reader
notes.Add(n); // add note to collection
}
}
}
// bind child
nestedRepeater.DataSource = notes;
nestedRepeater.DataBind();
Edit:
You might want to look into the DataAdapter - http://www.mikesdotnetting.com/Article/57/Displaying-One-To-Many-Relationships-with-Nested-Repeaters
I solved the problem by creating an additional connection string instead of reusing the same connection string I had been using for primary repeater. The Data is still not binding, but it does exist.
using (cmd2 = new SqlCommand("SELECT * FROM notes WHERE FID = 1356;", con2)) ;
I think the semicolon in your query may cause problems.
Try using quotation marks around the value like this:
SELECT * FROM notes WHERE FID = '1356;'
If the semicolon is not part of the value:
SELECT * FROM notes WHERE FID = '1356'

Using Winforms to connect to SQL Server to easily filter data

I have a Winforms that is connecting to a SQL Server 2008 database.
I would like to be able to easily filter through data in one table.
Here is an example of what I would like:
there are 3 columns in the table, and I will have three textboxes (or any other useful control) on a form that will correspond to those three columns.
the user will be able to input a value in any one of those fields and retrieve the rest of the values pertaining to that field.
Is there already an easy solution for this?
Yes you can use DataSet or DataReader.
http://msdn.microsoft.com/en-us/library/ms171897%28v=vs.80%29.aspx
http://www.dotnetperls.com/datagridview-tutorial
I don't think there is a yet unique way of doing this. Anyways, you can simply use a SqlCommand it will allow you to execute a storedprocedure or a query as you like. The you pass the three filter values as SqlParameters.
Here is a little example:
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT * FROM MyTable Where (FieldOne == #ParameterOne Or FieldTwo = #ParameterTwo Or FieldThree = #ParameterThree)";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
// Create the command
SqlCommand command = new SqlCommand(
queryString, connection);
// Add the parameters
command.Parameters.Add(new SqlParameter("ParameterOne", txtMyTextBox1.Text));
command.Parameters.Add(new SqlParameter("ParameterTwo", txtMyTextBox2.Text));
command.Parameters.Add(new SqlParameter("ParameterThree", txtMyTextBox3.Text));
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
Then you use the SqlDataReader to get the values.

Categories

Resources