c# .net Core OracleDataReader check count in results - c#

I know only one way how to count rows in results after ExecuteReader with this code:
while (er.Read()) {
count++;
}
How can I check with no while?

Short answer: you can't.
Long answer: ExecuteReader returns a forward-only sequential stream iterator, each time you advance one position you will point to and read one record until it reaches the end of the available data. Therefore it is impossible to know how many records you have until you have read all of them.
Here is a solution that may work for you, though.
Imagine you want to run this simple query: select * from Users
Even if you run this in your Oracle database directly, you won't know how many records you have until the query is executed. If you wanted to know the number of records you would use a count query, something like select count(*) from Users.
You can do the same using c#:
int count = 0;
using (var conn = new OracleConnection("Some connection string"))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "select count(*) from users";
count = (int)cmd.ExecuteScalar();
}
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "select * from users";
using(var reader = cmd.ExecuteReader())
{
while (reader.Read()) {
[...]
}
}
}
}

You could load your results into a DataTable and get the row count of of it:
using(var dt = new DataTable())
{
dt.Load(er); //assuming er is the OracleDataReader
}
Now you can read the rowCount with dt.Rows.Count.

Related

How to use C# connect to mysql and get json data?

As mentioned above:
I'm using C# to connect to a MySQL database and I want to read JSON data type.
I use the method MySqlCommand.ExecuteReader:
using (MySqlConnection sconn = new MySqlConnection(sqlConnectString))
{
sconn.Open();
String sql_Command = #"SELECT `id` FROM orders.jsontest;";
using (MySqlCommand scmd = new MySqlCommand(sql_Command, sconn))
{
**MySqlDataReader sdr = scmd.ExecuteReader();** // fatal error
DataTable datatable = new DataTable();
// ...
}
}
Can it be that I cannot use ExecuteReader here?
I know this question is old, but just in case you do not yet have a solution to your problem or anyone else encounters a similar problem, the following code should work for you:
private IEnumerable<int> GetIds()
{
using (MySqlConnection connection = new MySqlConnection(connectionString))
{
connection.Open();
string commandText = #"SELECT id FROM jsontest"; // Assuming that `orders` is your database, then you do not need to specify it here.
using (MySqlCommand command = new MySqlCommand(commandText, connection))
{
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
yield return reader.GetInt32(0);
}
}
}
}
Now what you should pay attention to is this line
while (reader.Read())
which fetches results from the jsontest table as long as the MySqlDataReader can still read valid results and this line
yield return reader.GetInt32(0);
which instructs the reader to get and return each record of the fetched table one at a time as an Int32 (int). You need to change this if your tables column type is not INT.
Since you selected just one column (i.e. "SELECT id"), the parameter is 0, because your fetched resul table consists of one column only.
Additionally, in your code you seem to want to get the results as a DataTable; if so, you should use MySqlDataAdapter instead of the MySqlDataReader as follows:
DataTable resultTable = new DataTable("ResultTable");
MySqlDataAdapter adapter = new MySqlDataAdapter(command);
adapter.Fill(table);
Correct your sql command
String sql_Command = #"SELECT id FROM orders.jsontest";

unreachable code detected on for loop

Tried finding similar from my problem but it seems there are too many unreachable code detectedmy table consist of 4 rows and I tried this code
using (MySqlConnection conn = new MySqlConnection(myConnection))
{
conn.Open();
MySqlCommand cmd = new MySqlCommand(query, conn);
int num = Convert.ToInt32(cmd.ExecuteScalar());
MySqlCommand cmd1 = new MySqlCommand(query2, conn);
MySqlDataReader reader = cmd1.ExecuteReader();
while (reader.Read())
{
for (int a = 0; a <= num; a++)
{
List li = new List();
li.linkLabel1.Text = reader["TitleAnime"].ToString();
flowLayoutPanel1.Controls.Add(li);
// break;
}
}
conn.Close();
}
but it gives me 16 values and thats too much then I tried putting break inside the for loop and I was able to achieve my goal and it gives me 4 values which is the same on my table but there seems to be an error called unreachable code detected..should I ignore it since I was able to get what I need? or is there another way for that
I'm pretty sure you are doing one query too much there, and you are getting NxN results because of that first query and of that for loop.
Try something like this:
using (MySqlConnection conn = new MySqlConnection(myConnection))
{
conn.Open();
MySqlCommand cmd1 = new MySqlCommand(query2, conn);
MySqlDataReader reader = cmd1.ExecuteReader();
while (reader.Read())
{
List li = new List();
li.linkLabel1.Text = reader["TitleAnime"].ToString();
flowLayoutPanel1.Controls.Add(li);
}
conn.Close();
}
If that does the job, consider in changing the name of the query1 and cmd1 to query and cmd since now you'll have only one of each
It's quite simple. You're running a for loop based on the number of entries you have in your database from the command object.
The read method will iterate four times if that's how many records you have in your database. Refer to this article for more information: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.read(v=vs.110).aspx.
In short, just remove the for loop and you'll get the result you want.
Try something like this:
while (reader.Read())
{
flowLayoutPanel1.Controls
.Add(new List { linkLabel1.Text = reader["TitleAnime"].ToString()});
}

Display the records that were updated C#

I have a simple update statement which updates locations where it is a certain Location. I am currently making a small desktop app where When I press a button, it will update and then display the records that were updated. How can I return the Ids of the records that were updated and then display those records in C#.
SqlCommand cmd = new SqlCommand(" update conset set location='LA' where deal in (select deal from dealset where location='LA') and locationid = 'NY'", con);
int rowsAffected = cmd.ExecuteNonQuery();
This however, only tells me the number of records that were updated not which ids were updated so I can query to display them. Help?
For example if 3 records were updated with the IDs: 1102, 1105, 111
Then it should display their Number based on the Id.
However, I am unsure how I can do that. How would I loop through the updated results.
I'd use an OUTPUT clause and loop the DataReader:
string sql = #"
UPDATE c
SET c.location = 'LA'
OUTPUT INSERTED.IdColumn
FROM conset c
WHERE deal IN (SELECT deal
FROM dealset
WHERE location = 'LA')
AND c.locationid = 'NY';";
List<int> updatedIDs = new List<int>();
using (var con = new SqlConnection(Properties.Settings.Default.ConnectionString))
using (var cmd = new SqlCommand(sql, con))
{
con.Open();
using (var rd = cmd.ExecuteReader())
{
while (rd.Read())
{
updatedIDs.Add(rd.GetInt32(0));
}
}
}

Checking the number of rows returned from MySQL Data Reader

I am currently working on an C# project and I am trying to get the number of rows returned from MySQL Data Reader.
I know there is no direct function so I am trying to write my own. In the function, I pass it the MySQLDataReader object and then loop through the MySQL Data Reader and increment a counter and return the value of the counter.
This then seems to lock up the program, I guess because I am Reader.read() after I've got the count I'm already at the end. Instead I have tried creating a copy of the reader and then loop through the temp version but I get the same result.
Below is my code where I am executing the query and calling the function.
string query = "SELECT * FROM reports, software, platforms, versions "
+ "WHERE EmailVerified = #verified AND reports.SoftwareID = software.id AND reports.PlatformID = platforms.id "
+ "AND reports.VersionID = versions.id AND BugReportAcceptedNotificationSent = #notificationSent";
using (MySqlCommand cmd = new MySqlCommand(query, db.conn))
{
cmd.Parameters.AddWithValue("#verified", "1");
cmd.Parameters.AddWithValue("#notificationSent", "0");
using (MySqlDataReader reader = cmd.ExecuteReader())
{
totalEmails = HelperClass.totalRowsInMySQLDataReader(reader);
while (reader.Read())
{
currentEmailCount++;
EmailNotifications emailNotification = new EmailNotifications(reader);
emailNotification.sendNewBugReportAfterVerificationEmail(currentEmailCount, totalEmails);
}
}
}
Below is my function that gets the row count
public static int totalRowsInMySQLDataReader(MySqlDataReader reader)
{
MySqlDataReader tempReader = reader;
ILibraryInterface library = GeneralTasks.returnBitsLibrary(Configuration.databaseSettings, Configuration.engineConfig.logFile);
string methodInfo = classDetails + MethodInfo.GetCurrentMethod().Name;
try
{
int count = 0;
while (tempReader.Read())
{
count++;
}
tempReader = null;
return count;
}
catch (Exception ex)
{
string error = string.Format("Failed to get total rows in MySQL Database. Exception: {0}", ex.Message);
library.logging(methodInfo, error);
library.setAlarm(error, CommonTasks.AlarmStatus.Medium, methodInfo);
return -1;
}
}
Make use of a DataTable to load your results, e.g.
DataTable dt = new DataTable();
dt.Load(reader);
int numberOfResults = dt.Rows.Count;
You can then also iterate over the rows to read the values, e.g.
foreach(DataRow dr in dt.Rows)
{
var value = dr["SomeResultingColumn"]
}
The other option is to issue two separate SQL statements, however you would need to ensure both statements were enclosed within a transaction with a Serializable isolation level, this is needed to make sure records aren't inserted between the execution of the two SQL statements.
To avoid multiple queries, how about including the total in the select itself?
SELECT COUNT(*) AS TotalNORows, * FROM reports, software, platforms, versions etc
i think without executing another command it's not possible...as there is no method available for count in reader class
you can try this... if it works..
string query = "SELECT * FROM reports, software, platforms, versions "
+ "WHERE EmailVerified=#verified AND reports.SoftwareID=software.id AND reports.PlatformID=platforms.id "
+ "AND reports.VersionID=versions.id AND BugReportAcceptedNotificationSent=#notificationSent";
using (MySqlCommand cmd = new MySqlCommand(query, db.conn))
{
cmd.Parameters.AddWithValue("#verified", "1");
cmd.Parameters.AddWithValue("#notificationSent", "0");
using (MySqlDataReader reader = cmd.ExecuteReader())
{
// create a new connection db.conn2 then
MySqlCommand cmd2 = new MySqlCommand(query, db.conn2))
cmd2.Parameters.AddWithValue("#verified", "1");
cmd2.Parameters.AddWithValue("#notificationSent", "0");
MySqlDataReader reader2 = cmd2.ExecuteReader();
int numberofrow=0;
while(reader2.Read())
numberofrow++;
//your codes......
}
Was working on the same problem. I hate having to iterate if a method is already available, but this is was the shortest bit I could come up with:
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader reader = cmd.ExecuteReader();
int rowcount = 0;
while(reader.Read()){
rowcount++;
}
First, create this class:
public static class Extensions
{
public static int Count(this MySqlDataReader dr)
{
int count = 0;
while(dr.Read())
count++;
return count;
}
}
This will implement .Count () on MySqlDataReader.
int count = reader.Count();
Exemple:
string sql= "SELECT * FROM TABLE";
MySqlCommand cmd = new MySqlCommand(sql, connection);
MySqlDataReader reader = cmd.ExecuteReader();
int count = reader.Count();
Maybe you could look things the other way around
You could just do a select count(*) and get the row count
or
use a data adapter to fill a container (like a DataTable) and count the rows
Unfortunatelly solution from Jan Van #Herck will return one row only, so in case you are interested in getting all rows and their number in one select, this isn't what you need.
In that case I suggest uou to try this:
select * , (select count(*) from my_table) AS numRow from my_table;
or read this:
Getting total mysql results returned from query with a limit: FOUND_ROWS error
You can use follwoing SQL Query to get the total rows Count.
SELECT COUNT(*) FROM [MYTABLE]
from the Code you can use ExecuteScalar() method to get the total number of rows returned by QUERY.
Try This:
int GetRowsCount(MySqlCommand command)
{
int rowsCount=Convert.ToIn32(command.ExecuteScalar());
return rowsCount;
}
Use above function as below:
MySqlCommand command=new MySlCommand("Select count(*) from MyTable",connectionObj);
int totalRows = GetRowsCount(command)
OleDbDataReader dbreader = new OleDbDataReader();
int intcount = 0;
if (dbreader.HasRows == true)
{
if (dbreader.Read())
{
intcount = dbreader.RecordsAffected;
}
}
"dbreader.RecordsAffected" will give you the number rows changed,inserted or deleted by the last statement of SQL

Limit your use of DataTable

I recently saw this, see below. I got OutofMemoryException when loading 2.5 million records with DataTable. And near the bottom, there is a table.Dispose(). Memory usage: 560Mb! Why use DataTable anyway?
public string[] GetIDs()
{
DataTable table = new DataTable();
using (SqlConnection dwConn = new SqlConnection(this.ConnectionString))
{
dwConn.Open();
SqlCommand cmd = dwConn.CreateCommand();
cmd.CommandText = "SELECT ID FROM Customer";
SqlDataReader reader = cmd.ExecuteReader();
table.Load(reader);
}
var result = new string[table.Rows.Count];
for(int i = 0; i < result.Length; i++ )
{
result[i] = table.Rows[i].ItemArray[0].ToString();
}
table.Dispose();
table = null;
return result;
}
I turned this in the following, and the memory used was now 250Mb for 2.5 million records, same as above. The memory used is now less than 45% of the original.
public IEnumerable<String> GetIDs()
{
var result = new List<string>();
using (var dwConn = new SqlConnection(ConnectionString))
{
dwConn.Open();
SqlCommand cmd = dwConn.CreateCommand();
cmd.CommandText = "SELECT ID FROM Customer";
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result.Add(reader["ID"].ToString());
}
}
}
return result;
}
Its good to see that you have a problem to your solution, but i would also recommend to have a look at this discussion which depicts that DataReader is a better solution than DataTable, but it depends on it use as well. After reading this you will understand memory consumption is expected to be less in case of DataReader.
Another advantage using SqlDataReader is documented in MSDN documentation is:
A part from Remarks:
Changes made to a result set by another process or thread while data
is being read may be visible to the user of the SqlDataReader.
So it is a possible reason that you are getting this difference in observation.
Hope it is useful for you and others as well.

Categories