How to work progressbar with values? - c#

My concept is For example here[COU] =45,then the progressbar load with that count and want to show completed successfully.
But am not getting the progress simultaneosly work with count here and does not show message also,please help me to do,my code is shown below
public void proget()
{
System.Data.DataRowView selectedFile =
(System.Data.DataRowView)dataGrid1.SelectedItems[i];
string iid = Convert.ToString(selectedFile.Row.ItemArray[10]);
SqlConnection con = new SqlConnection("Data Source=TNT3FMR\\SQLEXPRESS;Initial Catalog=xxx;Integrated Security=True");
string query = "SELECT [COU] FROM _Count_Series WHERE STUID='"+iid+"'";
SqlCommand cmd = new SqlCommand(query, con);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
progressBar1.Value++;
}
MessageBox.Show("Completed Successfully");
}

i'm not sure your design is right. best practices say you should close the db connection as soon as possible in a connected scenario. this means reading the data first and disposing of the reader before processing it. what you're doing is a little strange to me.
a problem i noticed in your code is that you build the query dynamically by concatenating strings. this opens you up to SQL injection attacks. you should use parametrized queries instead.
another problem is that you are not using the 'using pattern'. what happens if you get an error while connecting? how are the connection resources released?
from my personal experience, when i access a database i do it in an async manner and set the progressBar to an indeterminate state because i don't know how much it will take to read the data. your code is synchronous. this might be part of the reason why your UI doesn't update correctly.
hope this helps

Related

There is already an open DataReader associated with this Connection which must be closed first error in c# [duplicate]

I have below code and I am getting exception:
There is already an open DataReader associated with this Connection which must be closed first.
I am using Visual Studio 2010/.Net 4.0 and MySQL for this project. Basically I am trying to run another SQL statement while using data reader to do my other task. I am getting exception at line cmdInserttblProductFrance.ExecuteNonQuery();
SQL = "Select * from tblProduct";
//Create Connection/Command/MySQLDataReader
MySqlConnection myConnection = new MySqlConnection(cf.GetConnectionString());
myConnection.Open();
MySqlCommand myCommand = new MySqlCommand(SQL, myConnection);
MySqlDataReader myReader = myCommand.ExecuteReader();
myCommand.Dispose();
if (myReader.HasRows)
{
int i = 0;
// Always call Read before accessing data.
while (myReader.Read())
{
if (myReader["frProductid"].ToString() == "") //there is no productid exist for this item
{
strInsertSQL = "Insert Into tblProduct_temp (Productid) Values('this istest') ";
MySqlCommand cmdInserttblProductFrance = new MySqlCommand(strInsertSQL, myConnection);
cmdInserttblProductFrance.ExecuteNonQuery(); //<=====THIS LINE THROWS "C# mySQL There is already an open DataReader associated with this Connection which must be closed first."
}
}
}
You are using the same connection for the DataReader and the ExecuteNonQuery. This is not supported, according to MSDN:
Note that while a DataReader is open, the Connection is in use
exclusively by that DataReader. You cannot execute any commands for
the Connection, including creating another DataReader, until the
original DataReader is closed.
Updated 2018: link to MSDN
Always, always, always put disposable objects inside of using statements. I can't see how you've instantiated your DataReader but you should do it like this:
using (Connection c = ...)
{
using (DataReader dr = ...)
{
//Work with dr in here.
}
}
//Now the connection and reader have been closed and disposed.
Now, to answer your question, the reader is using the same connection as the command you're trying to ExecuteNonQuery on. You need to use a separate connection since the DataReader keeps the connection open and reads data as you need it.
Just use MultipleActiveResultSets=True in your connection string.
Add MultipleActiveResultSets=true to the provider part of your connection string
example in the file appsettings.json
"ConnectionStrings": {
"EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=YourDatabasename;Trusted_Connection=true;MultipleActiveResultSets=true"}
You are trying to to an Insert (with ExecuteNonQuery()) on a SQL connection that is used by this reader already:
while (myReader.Read())
Either read all the values in a list first, close the reader and then do the insert, or use a new SQL connection.
The issue you are running into is that you are starting up a second MySqlCommand while still reading back data with the DataReader. The MySQL connector only allows one concurrent query. You need to read the data into some structure, then close the reader, then process the data. Unfortunately you can't process the data as it is read if your processing involves further SQL queries.
This exception also happens if you don't use transaction properly. In my case, I put transaction.Commit() right after command.ExecuteReaderAsync(), did not wait with the transaction commiting until reader.ReadAsync() was called. The proper order:
Create transaction.
Create reader.
Read the data.
Commit the transaction.
You have to close the reader on top of your else condition.
In my case, I was awaiting an async call, but in the calling scope, I was not awaiting that method that I was making the call in. So, the calling scope was continuing on while my connection was still open.
called scope:
protected override async Task AfterProcessing()
{
var result = await Stats.WriteAsync();
Log.Information("Stopping");
}
calling scope:
public virtual async Task Run()
{
BeforeProcessing();
try
{
Process();
}
finally
{
AfterProcessing(); // this line was missing an "await"
}
}
There is another potential reason for this - missing await keyword.

Sloq SQL execution (calling store procedures) on huge site

First of all, I realize that my question MAY be broad, please bear with me as I've been thinking on how to form it for a month and I still am not 100% sure how to express my issues.
I'm currently developing a website, that will be used by many thousands of users daily. The bottle neck is the communication with the Data Base.
Each and every conversation with the tables is done through stored procedures, whose calls look like this:
public void storedProcedure(int id, out DataSet ds)
{
ds = new DataSet("resource");
SqlDataReader objReader = null;
SqlCommand cmd = new SqlCommand("storedProcedure", DbConn.objConn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#id", id));
openConnection(cmd);
SqlDataAdapter objDataAdapter = new SqlDataAdapter();
objDataAdapter.SelectCommand = cmd;
objDataAdapter.Fill(ds);
cmd.Connection.Close();
}
Or
public void anotherStoredProcedure(int var1, int var2, int var3, int var4, string var5, out DataSet ds)
{
ds = new DataSet("ai");
SqlCommand cmd = new SqlCommand("anotherStoredProcedure", DbConn.objConn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#var1", var1));
cmd.Parameters.Add(new SqlParameter("#var2", var2));
cmd.Parameters.Add(new SqlParameter("#var3", var3));
cmd.Parameters.Add(new SqlParameter("#var4", var4));
cmd.Parameters.Add(new SqlParameter("#var5", var5));
openConnection(cmd);
SqlDataAdapter objDataAdapter = new SqlDataAdapter();
objDataAdapter.SelectCommand = cmd;
objDataAdapter.Fill(ds);
cmd.Connection.Close();
}
My objConn is defined as following:
public static string DatabaseConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["objConnLocal"].ConnectionString;
public static SqlConnection objConn = new SqlConnection(DatabaseConnectionString);
And ofcourse in web.config I have
<add name="objConnLocal" connectionString="Initial Catalog=t1;Data Source=1.2.3.4;Uid=id;pwd=pwd;Min Pool Size=20;Max Pool Size=200;" providerName="SQLOLEDB.1"/>
Now the issue is: On every page_load there a few sp calls (above), and when the user starts navigating through the page, more calls are made.
At the moment only the developing and testing team are on the site and at times the speed is really slow. Frequently it would keep loading till it times out (err 504).
Another problem (only ever now and then, but certainly frequent enough to be noticeable) on first user login is it would keep trying to run a call but the connection would claim to be opened, even though it shouldn't be. A fairly not-working work-around is
private void openConnection(SqlCommand cmd){
if (cmd.Connection.State != ConnectionState.Closed)
{
cmd.Connection.Close();
}
if (cmd.Connection.State == ConnectionState.Open)
{
cmd.Connection.Close();
}
try
{
cmd.Connection.Open();
}
catch (Exception ex)
{
System.Threading.Thread.Sleep(1000);
HttpContext.Current.Response.Redirect("/");
}
}
Which makes connecting slow but at least doesn't show the YSOD.
So, what am I doing wrong on my SQL calls so that it is so slow for only 5-10 users? What I have so far:
I've read on Stack Overflow that using "using" is quite nice, but am not entirely sure why and how come as it was a single line comment under an answer. Another idea for improvement was to use several connection strings and not only one.
Resolved:
Changing the wait the connection is established in the connection string from username/pwd to Integrated Security resolved the issue. IF anyone's having similar issue refer to http://www.codeproject.com/Articles/17768/ADO-NET-Connection-Pooling-at-a-Glance
You're right - it's a broad question!
For context - many "thousands of users daily" isn't huge from a performance point of view. A well-built ASP.Net application can typically support hundreds of concurrent users on a decently specified developer laptop; assuming 10K users per day, you probably only have a few dozen concurrent users at peak times (of course this depends entirely on the application domain).
The first thing to do is to use a profiler on your running code to see where the performance bottleneck is. This is available in VS, and there are several 3rd party solutions (I like RedGate and JetBrains).
The profiler will tell you where your code is slow - it should be pretty obvious if it's taking seconds for pages to render.
At first glance, it looks like you have a problem with the database. So you can also use the SQLServer activity monitor to look at long-running queries.
Now the issue is: On every page_load there a few sp calls (above), and
when the user starts navigating trough the page, more calls are made.
This sounds like you've written webpages which won't display anything until the Stored Procedure calls have completed. This is never a good idea.
Shift these SP calls into a background thread, so the user at least sees something when they go onto the webpage (like a "Please wait" message). This can also help prevent timeout messages.
One other thing: you don't say why your SPs take so long to run.
If you're dealing with lots of records, its worth running a SQL script (described on the link below) to check for missing SQL Server indexes.
Finding missing indexes
This script shows the missing indexes which have made the most impact to your users, also tells you the syntax of the CREATE INDEX command you'd need to run to add those indexes.

Using MySql in ASP.NET: Does closing a connection really release table locks?

I'm working on an ASP.NET application where, as part of some logic, I want to lock some tables and do work on them. The method runs in a separate thread running as a kind of background task, spawned via a Task. The problem comes in with the error handling...
The code looks more or less like this:
MySqlConnection connection = new MySqlConnection(ConfigurationManager.AppSettings["prDatabase"]);
try
{
connection.Open();
MySqlCommand lock_tables = new MySqlCommand(Queries.lockTables(), connection);
lock_tables.ExecuteNonQuery();
// do a bunch of work here
MySqlCommand unlock_tables = new MySqlCommand(Queries.unlockTables(), connection);
unlock_tables.ExecuteNonQuery();
}
catch (MySqlException mex)
{
// Mostly error logging here
}
finally
{
connection.Close();
}
Pretty simple stuff. Everything works fine and dandy assuming nothing goes wrong. That's a terrible assumption to make, though, so I deliberately set up a situation where things would foul up in the middle and move to the finally block.
The result was that my table locks remained until I closed the app, which I learned by trying to access the tables with a different client once the method completed. Needless to say this isn't my intention, especially since there's another app that's supposed to access those tables once I'm done with them.
I could quickly fix the problem by explicitly releasing the locks before closing the connection, but I'm still left curious about some things. Everything I've read before has sworn that closing a connection should implicitly release the table locks. Obviously in this case it isn't. Why is that? Does connection.Close() not actually completely close the connection? Is there a better way I should be closing my connections?
Try wrapping your Connection and MySqlCommand instance in a using statement. That will release the objects as soon as it leaves the brackets.
using(MySqlConnection conn = new MySqlConnection(connStr))
{
conn.Open();
using(MySqlCommand command = new MySqlCommand("command to execute",conn))
{
//Code here..
}
}

c# SqlDatareader in my base class returns null connection error

I have a base class that contains a SqlDataReader which gets the data using a stored procedure, this works great until I return the data reader back up saying the connection is null.
Does anyone have any ideas? here's my code:
public SqlDataReader GetDataReader(string QueryName, SqlParameter[] Params)
{
SqlConnection conn = new SqlConnection(this.ConnectionString);
SqlDataReader reader;
using (conn)
{
SqlCommand command = new SqlCommand(QueryName,conn);
command.CommandType = CommandType.StoredProcedure;
if(Params !=null)
command.Parameters.Add(Params);
conn.Open();
reader = command.ExecuteReader();
}
// conn.Close();
return reader;
}
If you notice, I have the close part commented out, this was me trying to get it to work, for some reason when returning the datareader back up it is set to close???
Thanks!
You want to do the following:
SqlDataReader dr = command.ExecuteReader(CommandBehavior.CloseConnection)
and don't close the connection. When you close the datareader it will close it for you if you use the code above.
When using (conn) block finishes, it closes the database connection, that's why you are getting that error. Just delete that line.
You are using "using" which does the same things as calling conn.Close().
Because your connection is closed and disposed in using block before returning the reader . See this SO post
when you use using (conn) it automatically disposes the conn object
DataReader is a connected object. Means to get the data from the DataReader, the connection underneath need to be open at that moment. This is not so if you work with DataSets, which work in disconnected mode. You are closing the connection in your code before you return the DataReader. So the DataReader cannot give you any data.
A better design alternative might be providing the connection from outside (dependency injection).

Exception: There is already an open DataReader associated with this Connection which must be closed first

I have below code and I am getting exception:
There is already an open DataReader associated with this Connection which must be closed first.
I am using Visual Studio 2010/.Net 4.0 and MySQL for this project. Basically I am trying to run another SQL statement while using data reader to do my other task. I am getting exception at line cmdInserttblProductFrance.ExecuteNonQuery();
SQL = "Select * from tblProduct";
//Create Connection/Command/MySQLDataReader
MySqlConnection myConnection = new MySqlConnection(cf.GetConnectionString());
myConnection.Open();
MySqlCommand myCommand = new MySqlCommand(SQL, myConnection);
MySqlDataReader myReader = myCommand.ExecuteReader();
myCommand.Dispose();
if (myReader.HasRows)
{
int i = 0;
// Always call Read before accessing data.
while (myReader.Read())
{
if (myReader["frProductid"].ToString() == "") //there is no productid exist for this item
{
strInsertSQL = "Insert Into tblProduct_temp (Productid) Values('this istest') ";
MySqlCommand cmdInserttblProductFrance = new MySqlCommand(strInsertSQL, myConnection);
cmdInserttblProductFrance.ExecuteNonQuery(); //<=====THIS LINE THROWS "C# mySQL There is already an open DataReader associated with this Connection which must be closed first."
}
}
}
You are using the same connection for the DataReader and the ExecuteNonQuery. This is not supported, according to MSDN:
Note that while a DataReader is open, the Connection is in use
exclusively by that DataReader. You cannot execute any commands for
the Connection, including creating another DataReader, until the
original DataReader is closed.
Updated 2018: link to MSDN
Always, always, always put disposable objects inside of using statements. I can't see how you've instantiated your DataReader but you should do it like this:
using (Connection c = ...)
{
using (DataReader dr = ...)
{
//Work with dr in here.
}
}
//Now the connection and reader have been closed and disposed.
Now, to answer your question, the reader is using the same connection as the command you're trying to ExecuteNonQuery on. You need to use a separate connection since the DataReader keeps the connection open and reads data as you need it.
Just use MultipleActiveResultSets=True in your connection string.
Add MultipleActiveResultSets=true to the provider part of your connection string
example in the file appsettings.json
"ConnectionStrings": {
"EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=YourDatabasename;Trusted_Connection=true;MultipleActiveResultSets=true"}
You are trying to to an Insert (with ExecuteNonQuery()) on a SQL connection that is used by this reader already:
while (myReader.Read())
Either read all the values in a list first, close the reader and then do the insert, or use a new SQL connection.
The issue you are running into is that you are starting up a second MySqlCommand while still reading back data with the DataReader. The MySQL connector only allows one concurrent query. You need to read the data into some structure, then close the reader, then process the data. Unfortunately you can't process the data as it is read if your processing involves further SQL queries.
This exception also happens if you don't use transaction properly. In my case, I put transaction.Commit() right after command.ExecuteReaderAsync(), did not wait with the transaction commiting until reader.ReadAsync() was called. The proper order:
Create transaction.
Create reader.
Read the data.
Commit the transaction.
You have to close the reader on top of your else condition.
In my case, I was awaiting an async call, but in the calling scope, I was not awaiting that method that I was making the call in. So, the calling scope was continuing on while my connection was still open.
called scope:
protected override async Task AfterProcessing()
{
var result = await Stats.WriteAsync();
Log.Information("Stopping");
}
calling scope:
public virtual async Task Run()
{
BeforeProcessing();
try
{
Process();
}
finally
{
AfterProcessing(); // this line was missing an "await"
}
}
There is another potential reason for this - missing await keyword.

Categories

Resources