I am creating an automated DB Query Execution Queue, which essentially means I am creating a Queue of SQL Queries, that are executed one by one.
Queries are executed using code similar to the following:
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString))
{
cn.Open();
using (SqlCommand cmd = new SqlCommand("SP", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
}
}
}
}
What I would like to do is collect as much information as I can about the execution.
How long it took. How many rows were affected.
Most importantly, if it FAILED, why it failed.
Really any sort of information I can get about the execution I want to be able to save.
Try using the built in statistics for the execution time and rows selected/affected:
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString))
{
cn.Open();
cn.StatisticsEnabled = true;
using (SqlCommand cmd = new SqlCommand("SP", cn))
{
cmd.CommandType = CommandType.StoredProcedure;
try
{
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
}
}
}
catch (SqlException ex)
{
// Inspect the "ex" exception thrown here
}
}
IDictionary stats = cn.RetrieveStatistics();
long selectRows = (long)stats["SelectRows"];
long executionTime = (long)stats["ExecutionTime"];
}
See more on MSDN.
The only way I can see you finding out how something failed is inspecting the SqlException thrown and looking at the details.
While I am a bit unsure what your question really is, with that I mean if you want a list of statistics that could be useful to save or how to get the statistics you mention above.
SqlDataReader has properties .RecordsAffected and .FieldCount that tells you a bit about how much data was returned.
You can also catch the SqlException to find out some information about what (if anything) went wrong.
Related
Currently I am working on a C# project.
The purpose of the project is to read MySQL database records by executing select query.
To read the database records, I am using MySqlDataReader class and perform ExecuteReader() function.
Database connection and reading sample code.
using (MySqlConnection conn = new MySqlConnection(dbConnectionString))
{
conn.Open();
using (MySqlCommand command = new MySqlCommand(query, conn))
{
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// process data here
}
}
}
}
But getting below exception from reader.Read() function if there are huge number of records (i.e. 20000 or more).
MySql.Data.MySqlClient.MySqlException
HResult=0x80004005
Message=Fatal error encountered during data read.
Source=MySql.Data
StackTrace:
at MySql.Data.MySqlClient.MySqlDataReader.Read()
Inner Exception 1:
MySqlException: Reading from the stream has failed.
If there is anyone face the same, please share the solution. It will be highly appreciated.
Note: If there is same question available, please share the link.
You are most likely experiencing a timeout issue. If you know this query may take a long time to run, you can increase the timeout on this one MySqlCommand:
using (MySqlCommand command = new MySqlCommand(query, conn))
{
command.CommandTimeout = 600; // in seconds, i.e., ten minutes
....
Try changing the net timeout settings.
MySqlCommand cmd = new MySqlCommand("set net_write_timeout=99999; set net_read_timeout=99999", con);
cmd.ExecuteNonQuery();
I am working on a project in VS13 and SQL Server 2012 and I am facing a little problem. I can't seem to be read data from my database. It throws exception whenever I try to do any operation on the SqlDataReader object I use to read the data.
The exception I am getting is InvalidOperationException.
Look at this code of mine, I call this function with the SQL query as the parameter and stores the returned object in another SqlDataReader object.
private SqlDataReader reader (string sqCommand)
{
myConnection.Open();
string string1;
string1 = sqCommand;
SqlDataReader a = null;
try
{
SqlCommand Newcommand = new SqlCommand(string1, myConnection);
a = Newcommand.ExecuteReader();
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
myConnection.Close();
if (a.Read()) //**statement 1**
return a;
else
return null;
}
I gets the exception in the statement 1 marked in the code above and in every operation I perform on the object a or the object that receives this.
Can anyone please tell me what is wrong with my code or provide any other explanation? If more other parts of the code is needed for the purpose of finding for the error, I can provide it.
Thanks for the time and the help you may provide. :)
Your connection needs to stay open while you're using the SqlDataReader. A more conventional use for your SqlDataReader would be as follows:
private List<object> Reader(string sqCommand)
{
using (SqlConnection myConnection = new SqlConnection(ConnectionString))
{
myConnection.Open();
using (SqlCommand cmd = new SqlCommand(sqCommand, myConnection))
using (SqlDataReader reader = cmd.ExecuteReader())
{
List<object> list = new List<object>();
while (reader.Read())
{
list.Add(reader[0]);
}
return list;
}
}
}
I'm trying to figure out which is more efficient to run. I have a foreach of tables and I'm wondering if it should be outside of my using or inside of it. Examples below.
the using (SqlConnection) inside of the foreach:
foreach (string tableName in desiredTables)
{
using (SqlConnection connection = new SqlConnection(cloudConnectionString))
{
connection.Open();
string query = string.Format("SELECT id, active, createdon, modifiedon FROM {0}", tableName);
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
SqlDataAdapter dAdapter = new SqlDataAdapter(cmd);
try
{
dAdapter.Fill(dSet, tableName);
}
catch
{
throw;
}
}
}
}
Versus the foreach inside of the using (SqlConnection):
using (SqlConnection connection = new SqlConnection(cloudConnectionString))
{
connection.Open();
foreach (string tableName in desiredTables)
{
string query = string.Format("SELECT id, active, createdon, modifiedon FROM {0}", tableName);
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
SqlDataAdapter dAdapter = new SqlDataAdapter(cmd);
try
{
dAdapter.Fill(dSet, tableName);
}
catch
{
throw;
}
}
}
}
I'm trying to optimize this for a faster pull from the DB and I'm not sure which way is recommended/better. Advice would be great.
You'll have to try it and measure it to be certain, but I doubt you'll see a huge difference either way. Connections are pooled by .NET, so creating them in a loop (I'm assuming you just have a handful of tables, not several hundred) should not be a significant bottleneck. You'll likely spend a LOT more time in network I/O and actually populating the DataSet (which does have a lot of overhead).
Bottom line - fine one way that works (so you have something to revert back to) and try it multiple ways and see if one method makes a significant difference to the application overall.
Generally, Open and Close a database connection multiple times in a network environment can be expensive (connection data travels thru your network several rounds, the C# CLR has to allocate and free resource several times, the Garbage Collection has more works to do later...), so you should try to reuse your database connection by putting it outside the loop.
I've written a function to perform MySQL statements. In this function I give in a statement and get back the MySqlDataReader, but the problem is my function do not close the connection. After a short while of using the Programm, it crashs because the new connection can't be open. This is the error i got by trying open the new connection:
error connecting: Timeout expired. The timeout period elapsed prior
to obtaining a connection from the pool. This may have occurred
because all pooled connections were in use and max pool size was
reached.
My code look like this:
MySQL Class:
class mySql
{
string cs = "server=123.123.123.123;" +
"uid=abcabc;" +
"pwd=123456;" +
"database=overflow_test;";
private MySqlConnection conn_f() // create a Connection
{
MySql.Data.MySqlClient.MySqlConnection conn;
conn = new MySql.Data.MySqlClient.MySqlConnection();
conn.ConnectionString = cs;
try
{
conn.Open();
return conn;
}
catch
{
return null;
}
}
public MySqlDataReader CMD_f(string comand) //execute SQL Command
{
MySql.Data.MySqlClient.MySqlCommand cmd;
cmd = new MySql.Data.MySqlClient.MySqlCommand();
MySqlConnection conn = conn_f();
cmd.Connection = conn;
cmd.CommandText = comand;
cmd.Prepare();
rdr = cmd.ExecuteReader();
return rdr;
}
}
and an example how i use it Main Class
class main{
mySql DB = new mySql();
public void main(){
MySqlDataReader rdr = DB.CMD_f("SELECT * FROM tbl_kategorie");
int i = 0;
while (rdr.Read())
{
string str = rdr.GetString(1);
Console.WriteLine(str);
}
}
Has someone an Idea to solve the Problem.
Sincere regards LFS96 (Fabian Harmsen)
The main problem is the inbalance in the code. The CMD_f method creates a connection, but doesn't take responsibility for it. You should rather make the method that creates the connection public, so that you can take responsibility for it in the code that can close it.
That's a bigger change, so first let's look at a smaller change to fix the code.
The data reader should expose the data connection as the Connection property. I don't see that in the documentation, so it's possible that it doesn't, but the data readers in the .NET framework does.
If the property is exposed, then you can make a quick fix to make the code work with minimal change:
MySqlDataReader rdr = DB.CMD_f("SELECT * FROM tbl_kategorie");
int i = 0;
while (rdr.Read())
{
string str = rdr.GetString(1);
Console.WriteLine(str);
}
rdr.Close();
rdr.Connection.Close();
If you make the conn_f method public and don't call it in the CMD_f method, you can write much more robust code, that never leaves a connection or data reader hanging even if there is an error. That's a bigger change in the code, but definitely worth the effort when you have time to implement and test it. Using a using block to make sure that the objects are always disposed correctly makes the code much more resilient:
using (MySqlConnection conn = DB.conn_f()) {
using (MySqlDataReader rdr = DB.CMD_f(conn, "SELECT * FROM tbl_kategorie")) {
int i = 0;
while (rdr.Read()) {
string str = rdr.GetString(1);
Console.WriteLine(str);
}
}
}
Side note: Identifiers in C# tend to be descriptive. I suggest names like DB.CreateConnection and DB.ExecuteReader rather than DB.conn_f and DB.CMD_f.
I want to use an Access database for my Windows Forms application. (written with C#)
I have used OleDb namespace for connecting, and I'm able to select the records from the source using the OleDbConnection and ExecuteReader objects.
However, I can't insert, update or delete records yet.
My code is the following:
OleDbConnection con = new OleDbConnection(strCon);
try
{
string con="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=xyz.mdb;Persist Security Info=True";
con.Open();
OleDbCommand com = new OleDbCommand("INSERT INTO DPMaster(DPID, DPName, ClientID, ClientName) VALUES('53', 'we', '41', 'aw')", con);
int a = com.ExecuteNonQuery();
//OleDbCommand com = new OleDbCommand("SELECT * FROM DPMaster", con);
//OleDbDataReader dr = com.ExecuteReader();
//while (dr.Read())
//{
// MessageBox.Show(dr[2].ToString());
//}
MessageBox.Show(a.ToString());
}
catch
{
MessageBox.Show("cannot");
}
If I the commentted block is executed, the application works fine. But the insert block doesn't.
Knowing this, why I am unable to insert, update or delete database records?
the problem that I encountered myself is as:
You've added the mdb file to your solution and every time you run the program it will be copied into debug folder.
So you can select from it but deleting rows doesn't affect the original file you have in your solution.
Check for it.
First, never strangle your exception. It is better to let your exception bubble up so that you may get important information regarding what is not working properly. It is better to write:
con.Open();
OleDbCommand com = new OleDbCommand("INSERT INTO DPMaster(DPID,DPName,ClientID,ClientName) VALUES('53','we','41','aw')", con);
int a = com.ExecuteNonQuery();
than
try {
con.Open();
OleDbCommand com = new OleDbCommand("INSERT INTO DPMaster(DPID,DPName,ClientID,ClientName) VALUES('53','we','41','aw')", con);
int a=com.ExecuteNonQuery();
} catch {
MessageBox.Show("cannot");
}
Second, make use of using blocks as much as possible, since those blocks will dispose the no longer needed objects. So your code should look like this:
using (OleDbConnection con = new OleDbConnection(conStr))
using (OleDbCommand com = new OleDbCommand("INSERT INTO DPMaster(DPID,DPName,ClientID,ClientName) VALUES('53','we','41','aw')", con) {
con.Open();
int a = com.ExecuteNonQuery();
MessageBox.Show(a.ToString());
}
With this code, you will more likely get to know what is going wrong while the exception will bubble up, plus, as soon as you'll quit the scope of the using blocks, resources used will be freed up as your objects will get disposed.