I am retrieving 10 rown from my database but I want to skip the first one. Reason being that the first item in my table is already displayed within the main div on my page. Now I want to list all the other remaining records underneath it. How do I accomplish this?
My code works ok and I can display all records from the reader. All I need now is how to skip the first one.
Just read the first one, then continue with the others:
myReader.Read();
while(myReader.Read())
{
//do stuff
}
If you like to use Linq, here's a trick to make it work with DataReaders, using a simple extension method :
public static IEnumerable<IDataRecord> AsEnumerable(this IDataReader reader)
{
while (reader.Read())
{
yield return reader;
}
}
You can then use the Linq Skip method :
using (var reader = command.ExecuteRead())
{
foreach(var row in reader.AsEnumerable.Skip(1))
{
// whatever you do with the data...
}
}
Just call reader.Read() one extra time to start with, to advance to the next record. Then treat the reader as normal. You may want to still check the value of reader.Read() from that first call - if it returns false then there wasn't even the first record you were expecting.
I can't help thinking that there's got to be something else "wrong" when you require skipping the first row in your DataReader like:
Maybe your SQL query, sproc or whatever should exclude the first row instead?
Why do you already have your first row? Maybe you could get all the rows at the same time?
Your question implies a lack of coding experience - either in general or with regards to DataReader or something. Maybe you could get even more help if you explained why you need to skip the first row?
Related
I am using DataTable.Load(IDataReader) to load data from db.
When I load one record, DataTable.Rows.Count shows a count of 0, but when I load more than record DataTable.Rows.Count shows the right Count.
Does this mean DataTable.Load Method takes two rows and above?
This article was helpful but didn't answer my question
https://msdn.microsoft.com/en-us/library/system.data.datatable.load(v=vs.110).aspx.
Code
DataTable dt= new Datable
IDataReader rsg = DataClass.GetDBResults("sp_GetNames", "#Names", names);
if (rsg.Read())
{
dt.Load(rsg);
int num = dt.Rows.Count;
//More Code
}
num is 0 if the procedure,sp_GetNames returns one record.
You're calling Read(), which reads the first record, and then you're calling Load(). The problem is that, after calling Read(), the pointer to the "current record" in rsg has already moved past the first record and is pointing to the next record (if there is one). The call to Load() is only going to read the rest of the records, since IDataReader is a forward-only mechanism.
Call Load() without the first call to Read().
I read an excel file and put it in a Datatable.
If I put a breakpoint and inspect the value of myDatatable.Rows.Count() it is equal to the number of rows in my excel file.
But then I pass my datatable object to a method like this:
private void Foo(Datatable dt)
{
DataTableReader reader = dt.CreateDataReader();
while(reader.Read())
{
// do stuff on each row
}
}
Now if I put a counter inside my while loop, it shows for example 10 while the number of rows are really 100000.
What is it I am doing wrong?
That should work similar to a for-each loop on DataTable.Rows
I am guessing somewhere in your while loop you are exiting out of the loop. Make sure you have used "break" and "continue" correctly.
What makes you think anything's wrong? The table will have e.g. 100000 rows, that won't change. The DataReader, iterating over the table one row at a time, will have a different position on each iteration.
I am getting this error: Data Could not be read. Data is Null. This method or property cannot be called on Null values.
I know the Database has NULL values in some fields. I just want to handle them and continue filling in the next row. Here's some code:
rdr is the SqlDataReader
if (rdr[EmailID] != null)
{
//this blows up on this line on the 32nd iteration of the loop when searching for an extended group.
EmpNewData.SelectSingleNode("/my:myFields/my:Emp/my:EmpData/my:email", NamespaceManager).SetValue(rdr.GetString(EmailID));
}
else
{
EmpNewData.SelectSingleNode("/my:myFields/my:Emp/my:EmpData/my:email", NamespaceManager).SetValue("No.Email");
}
I could handle this with the Stored Procedure, but I'd really like to know how to handle this. Above is one of many iterations I've tried.
Thanks.
I figured this out. IsDBNull seems to take care of it. I ran thru the code in debug to check where the ordinal sat. It was 14 in this case.
int EmailID = rdr.GetOrdinal("EmailID");
Then when using GetString:
if (!(rdr.IsDBNull(14)))
{
EmpNewData.SelectSingleNode("/my:myFields/my:Emp/my:EmpData/my:email", NamespaceManager).SetValue(rdr.GetString(EmailID));
}
else
{
EmpNewData.SelectSingleNode("/my:myFields/my:Emp/my:EmpData/my:email", NamespaceManager).SetValue("No Email");
}
I hope this will help somebody.
I haven't used DataReaders in ages (I prefer to use an ORM) but I'm forced to at work. I pull back the rows, and check that HasRows is true; debugging at this point and examining the reader shows that my data is there.
Now here's the issue: the moment I call reader.Read(), trying to expand the results says "The enumeration yielded no results" or whatever, and I get the "Invalid attempt to read when no data is present." error. I get the same thing if I don't call Read() (which is the default since the DataReader starts before the first record).
I cannot remember the proper way to handle this; the data is there when I check HasRows, but is gone the moment I either try to read from it right after or after I call Read, which makes no sense as if I don't call Read, the reader should still be before the first record, and if the property is set that starts it at the first record (SingleRow? I forget the name of it) is set, then I should be able to read rows without calling Read, however both ways seem to move past the row containing the data.
What am I forgetting? Code is fairly straightforward:
TemplateFile file = null;
using (DbDataReader reader = ExecuteDataReaderProc("GetTemplateByID", idParam))
{
if (reader.HasRows) // reader has data at this point - verified with debugger
{
reader.Read(); // loses data at this point if I call Read()
template = new TemplateFile
{
FileName = Convert.ToString(reader["FileName"]) // whether or not I call
// Read, says no data here
};
}
}
Just to clarify the answer, it was using the debugger since expanding the results view calls Read() and therefore it moves past the row. As Marc Gravell said in a comment: Debugger considered harmful
If you want to put the data into a file, start by loading a DataTable instead of using a DataReader.
With the DataReader, as has been mentioned in the comments, you might want to iterate through the result set with a while loop
while (reader.Read())
{
}
The loop reads one row at a time and quits when all of the rows have been read.
Once you move to the next row, the previous rows are no longer available unless you have put them into some other structure, like a list or DataTable.
But you can use a DataAdapater to fill a DataTable so there might not be a reason to use a DataReader. Then you can write to a file from the DataTable.
In any event, I don't see how this line could work.
FileName = Convert.ToString(reader["FileName"])
I can post additional code for either approach if you like.
HTH Harvey Sather
The following post relates to the System.Data.SQLite data provider by phxsoftware (http://sqlite.phxsoftware.com)
I have a question (and possibly a problem) with DbDataReader’s Read method and/or Visual Studio 2008. In many examples I see things like the following (and I know this code doesn't make a lot of sense ... but it serves a purpose):
DbDataReader reader = null;
Long ltemp = 0;
lock (m_ClassLock)
{
DbCommand cmd = dbCnn.CreateCommand();
cmd.CommandText = “SELECT col1 FROM table1”;
reader = cmd.ExecuteReader();
if (null != reader)
{
while (reader.Read())
{
ltemp += (long)reader[0];
}
}
reader.Close();
First question - What I dont understand from this example is am I missing data the first time through the while loop by calling reader.Read() upfront? For instance, if the reader has values (3,5,7,9) the returned reader from cmd.ExecuteReader() should be pointing at 3 initially, correct? reader.Read() would then move to 5, 7, and 9 on subsequent invocations within the while loop. But, because reader.Read() is invoked before the first "ltemp += ..." line am I skipping past the first result (3)?
Second question - (and I'm starting to think this might be a bug in VS) If I step through this set of code in the debugger when I stop at a breakpoint on the "if (null != ..." line I can clearly see mu mousing over and drilling down in the popup that reader has multiple row data values assigned to it. However, if I close that popup information, and then try to bring it back up, when I drill down I now see the line "Enumeration yielded no results" where there was clearly data before.
Can anyone explain this behavior?
Think about it like this after you run ExecuteReader the set is on row -1. You need to execute Read to get to row 0.
IDataReader is a forward only structure, you can only iterate through it once, the debugger is iterating through it.
General questions:
Why the lock?
Why the null check for reader - I am not aware of any issues where ExecuteReader return null after a select.
Why not "SELECT SUM(col1) from table1
Why are you not following the dispose pattern?