I have problem with my homework code. We must create some database with updating users, but I am getting error with these and program crash..
This is full error code and there is code..
Error: MySql.Data.MySqlClient.MySqlException (0x80004005): 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.
I try with query.CommandTimeout = 60; but i think its useless, what do u think?
MySqlConnection connect = new
MySqlConnection("Server=localhost;Database=Work;Uid=root;Pwd='1234';");
connect.Open();
MySqlCommand query = new MySqlCommand(#"UPDATE user
SET User_Name=#User_Name,User_BankBalance=#User_BankBalance,
User_Password=#User_Password,LottoTimer=#LottoTimer
WHERE User_Name='" + Escape(u.Username) + "'", connect);
using (query)
{
query.CommandType = System.Data.CommandType.Text;
query.Parameters.AddWithValue("#User_Name", Escape(u.Username));
query.Parameters.AddWithValue("#User_BankBalance", u.BankBalance);
query.Parameters.AddWithValue("#User_Password", u.Password);
query.Parameters.AddWithValue("#LottoTimer", u.LottoTimer);
query.Dispose();
query.Prepare();
query.ExecuteNonQuery();
}
connect.Close();
return;
You method should look something like this:
string query =
#"UPDATE user SET"
+ " User_Name=#User_Name,"
+ " User_BankBalance=#User_BankBalance,"
+ " User_Password=#User_Password,"
+ " LottoTimer=#LottoTimer"
+ " WHERE User_Name='" + Escape(u.Username) + "'";
using( var connect = new MySqlConnection("Server=localhost;Database=Work;Uid=root;Pwd='1234';"))
using( var query = new MySqlCommand(query, connect))
{
connect.Open();
query.CommandType = System.Data.CommandType.Text;
query.Parameters.AddWithValue("#User_Name", Escape(u.Username));
query.Parameters.AddWithValue("#User_BankBalance", u.BankBalance);
query.Parameters.AddWithValue("#User_Password", u.Password);
query.Parameters.AddWithValue("#LottoTimer", u.LottoTimer);
query.Prepare();
query.ExecuteNonQuery();
}
return;
It is important to dispose the MySqlConnection, so it can be available to the pool again. The problem you have is that all connections are used in the pool, and it is waiting for one - until the timeout.
Related
I get error trying to work with transactions. Without it everything runs fine, but with it I get a strange error: the transaction is completed and cannot be utilized anymore (my translation of the error)
Here is my code till the error:
using (var conn = new SqlConnection(gl.constr))
{
using (SqlCommand cm = new SqlCommand())
{
conn.Open();
using (SqlTransaction tr = conn.BeginTransaction())
{
try
{
cm.Connection = conn;
cm.Transaction = tr;
cm.CommandText = "INSERT INTO Bookings (Time, Price, BookingRef, BookingInternalRef)" +
" VALUES(" +
"getdate(), "+ sPrice + ", " +
db.AddAphens(reference) + ", " +
db.AddAphens(internalBookref) +
")";
cm.ExecuteNonQuery(); //this works
tr.Commit();
On the commit the error popups.
You don't need a explicit transaction declaration SqlTransaction tr = conn.BeginTransaction() for a single DML operation since every DML operation will be implicit transaction bound. Thus you can remove your transaction declaration all-together and it should work fine
System.Data; 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.
this error will come only when i run service
i am using below code
try
{
LogGenerator.WriteErrorLog("Conn opened before");
if (con.State == System.Data.ConnectionState.Closed)
con.Open();
LogGenerator.WriteErrorLog("Conn opened");
// Set up a command with the given query and associate
// this with the current connection.
SqlCommand cmd = new SqlCommand("Backup database " + DBName + " to disk='" + filePathExist + "'", con);
cmd.ExecuteNonQuery();
LogGenerator.WriteErrorLog("query executed");
}
catch(Exception ex)
{
LogGenerator.WriteErrorLog("Error in Conn");
LogGenerator.WriteErrorLog(ex);
}
finally
{
con.Close();
con.Dispose();
SqlConnection.ClearPool(con);
}
As your trying take DB backup sometime it will take more than default connection time, so try to set timeout to your command.
try
{
if (con.State == System.Data.ConnectionState.Closed)
con.Open();
// Set up a command with the given query and associate
// this with the current connection.
SqlCommand cmd = new SqlCommand("Backup database " + DBName + " to disk='" +
filePathExist + "'", con);
cmd.CommandTimeout = 60;
cmd.ExecuteNonQuery();
}
catch(Exception ex)
{
//handle exception here
}
finally
{
con.Close();
con.Dispose();
SqlConnection.ClearPool(con);
}
for more information on timeout please refer here.
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout(v=vs.110).aspx
https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-remote-login-timeout-server-configuration-option
I have a c# console app client and I am trying to connect to mysql database.
I have a main method called select.
This method return n of rows.
I am looping through results, and for each one I am calling another method call GetProductAttributes and after I get the results I am calling another method called UpdateProductAttributesJsonField
Here is my code :
public void Select(int shopId)
{
using(MySqlCommand cmd = new MySqlCommand("GetProducts", new MySqlConnection(connection.ConnectionString)))
{
cmd.Parameters.Add(new MySqlParameter("#last_modified_date", ""));
cmd.Parameters.Add(new MySqlParameter("#ShopId", shopId));
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection.Open();
MySqlDataReader dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while (dataReader.Read())
{
var id = int.Parse(dataReader["Id"].ToString());
var attributes = GetProductAttributes(id);
var json = JsonConvert.SerializeObject(attributes.ToArray());
UpdateProductAttributesJsonField(id, json);
}
//dataReader.Close();
}
}
public Dictionary<string, string> GetProductAttributes(int Id)
{
var result = new Dictionary<string, string>();
using(MySqlCommand cmd = new MySqlCommand("GetProductAttributes", new MySqlConnection(connection.ConnectionString)))
{
cmd.Parameters.Add(new MySqlParameter("#Id", Id));
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection.Open();
//CommandBehavior.CloseConnection
MySqlDataReader dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while (dataReader.Read())
{
result.Add(dataReader["name"].ToString(), dataReader["value"].ToString());
}
//dataReader.Close();
}
return result;
}
public void UpdateProductAttributesJsonField(int productId, string json)
{
using( MySqlCommand cmd = new MySqlCommand("UpdateArticleAttributes", new MySqlConnection(connection.ConnectionString)))
{
cmd.Parameters.Add(new MySqlParameter("#articleId", productId));
cmd.Parameters.Add(new MySqlParameter("#json", json));
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
//cmd.EndExecuteNonQuery(CommandBehavior.CloseConnection); // cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
Here is my initialize method
private void Initialize()
{
server = ConfigurationManager.AppSettings["ShopwareDBServer"];
database = ConfigurationManager.AppSettings["DatabaseName"];
uid = ConfigurationManager.AppSettings["DatabaseUser"];
password = ConfigurationManager.AppSettings["DatabasePassword"];
port = "3306";
string connectionString;
connectionString = "SERVER=" + server + ";" + "Port=" + port + ";" + "DATABASE=" +
database + ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";" + "Convert Zero Datetime=True";
connection = new MySqlConnection(connectionString);
}
I am getting this error :
{"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."}
Since you are using Data Reader in your code, you need to close the connection before opening a new one.
It may seem to be a suggestion rather than answering the question, but let me show you another way to do the same thing.
You want to call 3 procedures then why you are not combining these three procedures and create a new one in the database and call that procedure. I think, this way you need only one connection and your problem will be solved.
By the way, this is not possible to call three procedures on the same connection that uses "Data Reader".
You can check whether the connection state is opened or closed; this can help you decrease your maximum connection pool size.
You can write the code like this:
If(Connection.State == Closed) {
Connection.open
}
This is because you use maximum connection pool size may be in your code you no where write connection.close() so connection size is increase with time so just make sure you close connections in finally block.
First restart MySQL so it will close all the connection and change your code accordingly. And this issue is not due to calling 3 stored procedures in one connection and if you want to do it is done in multiple way.
Either you call one stored procedure and call other procedures from the first one.
You also call stored procedures step by step from c# code as well.
I have a frustrating issue with a query that typically takes between 1.5-2 minutes to run (due to a lack of ability to modify this database, we cannot improve it more than this time). The query times out, despite the Command Timeout property being set to 0 (this is C# code).
Here is the code that executes the query:
public DataTable GetData()
{
DataTable results = new DataTable();
try
{
using (var sqlConnection = new SqlConnection(ConfigurationManager.AppSettings["SqlConnectionString"].ToString()))
{
String command = _query;
sqlConnection.Open();
var sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = command;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandTimeout = 0;
SqlDataAdapter daM = new SqlDataAdapter(sqlCommand.CommandText, sqlConnection);
daM.Fill(results);
sqlConnection.Close();
}
}
catch(Exception e)
{
Console.WriteLine("Error " + e.StackTrace);
}
Console.WriteLine("Retrieving results for query " + _query);
Console.WriteLine("Total Results: " + results.Rows.Count);
return results;
}
I'm not sure where to look for the culprit. Setting a more explicit timeout does nothing, and as I said there's no way to further improve the query that we've been able to find. The connection string has the following parameters:
server =
Integrated Security = SSPI
database =
Connection Timeout = 0
Any advice of where I should look next? We are using Microsoft SQL Server.
You have set sqlCommand.CommandTimeout, but later you've created SqlDataAdapter as
SqlDataAdapter daM = new SqlDataAdapter(sqlCommand.CommandText, sqlConnection)
Here adapter implicitly creates and uses new SqlCommand (not the one you've configured) since you've passed there command text, not instance of SqlCommand.
Use another constructor of SqlDataAdapter and create it like
SqlDataAdapter daM = new SqlDataAdapter(sqlCommand)
Set timeout on SqlConnection does not work in your case, you need do it on SqlDataAdapter.
daM.SelectCommand.CommandTimeout = Value;
Google for "How do you change a SqlDataAdapter .CommandTimeout?"
I keep getting the error in GetTotalMaterialCost I have already checked the whole thing. I even remove excess con.Close but the error will still prompt t it.
decimal GetTotalMaterialCost()
{
decimal total = 0;
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText =
"SELECT SUM(rm.Quantity * m.SellingPrice) AS TotalMaterialCost FROM Resource_Materials rm " +
"JOIN Materials m ON m.MaterialID = rm.MaterialID " +
"JOIN ProjectTasks t ON t.TaskID = rm.TaskID " +
"WHERE t.TaskID=#TaskID HAVING COUNT (*) > 0";
cmd.Parameters.AddWithValue("#TaskID", Request.QueryString["ID"].ToString());
object data = cmd.ExecuteScalar();
if (data == null)
total = 0;
else
total = (decimal)cmd.ExecuteScalar();
con.Close();
return total;
}
protected void btnSave_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "UPDATE ProjectTasks SET Name=#Name, Description=#Description " +
"WHERE TaskID=#TaskID; " +
"SELECT TOP 1 TaskID FROM ProjectTasks ORDER BY TaskID DESC;";
cmd.Parameters.AddWithValue("#Name", txtName.Text);
cmd.Parameters.AddWithValue("#Description", txtDescription.Text);
cmd.Parameters.AddWithValue("#TaskID", Request.QueryString["ID"].ToString());
cmd.ExecuteNonQuery();
cmd.CommandText = #"UPDATE Resource_Materials SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Equipments SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Vehicles SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Resource_Contractors SET TaskID=#TaskID WHERE TaskID=0; " +
"UPDATE Projects SET ActualCost=#ActualCost WHERE ProjectID=#ProjectID";
cmd.Parameters.AddWithValue("#ProjectID", Request.QueryString["ID"].ToString());
cmd.Parameters.AddWithValue("#ActualCost", GetAmount());
con.Close();
Helper.AddLog("1", "Add", "Assigned Resources to Task");
Response.Redirect("~/Projects/Default.aspx");
}
Here is the link for my whole code as reference
The said error is at line 679
This usually happens because you use a global connection object and somewhere in your code the connection was not properly closed. For example, an exception is triggered somewhere in your code and you forget to close the connection in that case.
The resolution is always the same.
Do not keep a global connection object.
Create it when you need it and destroy it with the appropriate syntax.
There is connection pooling infrastructure in ADO.NET that has been devised just to give better performance when you are in a create/open/use/close scenario.
decimal GetTotalMaterialCost()
{
decimal total = 0;
string query = #"SELECT SUM(rm.Quantity * m.SellingPrice) AS TotalMaterialCost
FROM Resource_Materials rm
JOIN Materials m ON m.MaterialID = rm.MaterialID
JOIN ProjectTasks t ON t.TaskID = rm.TaskID
WHERE t.TaskID=#TaskID HAVING COUNT (*) > 0";
using(SqlConnection con = new SqlConnection(....constringhere...)
using(SqlCommand cmd = new SqlCommand(query, con))
{
con.Open();
.....
}
return total;
}
In this way the connection object is local and the using statement ensures that is closed and disposed at the closing brace even if you hit some kind of exception.
Of course this pattern should be applied in every point where you try to reach your database and the global connection object should be removed. The only thing that could be kept global is the connection string and also for this there is a better place to store it (IE. The app.config ConnectionString section)
Said that it is a possibility that you have an error caused by the AddWithValue usage. This method defines the DataType of the parameter looking at the value passed. It seems that your TaskID field is an integer, but you prepare a parameter with AddWithValue and pass a string. So the query will use a parameter with the wrong datatype.
I suggest to use
cmd.Parameters.Add("#TaskID", SqlDbType.Int).Value =
Convert.ToInt32(Request.QueryString["ID"].ToString()));
Finally, just give a cursory glance to your code, I suggest to change the methods called by your Page_Load to receive a connection object opened directly in the Page_Load event
if (!IsPostBack)
{
using(SqlConnection con = new SqlConnection(....constringhere...)
{
GetProjectMaterials(con);
GetProjectEquipments(con);
GetProjectVehicle(con);
GetProjectContractors(con);
GetTasks(con,resourceID);
GetMaterials(con);
GetEquipments(con);
GetVehicles(con);
GetLContractors(con);
}
}
Of course you need to change also the other methods that calls these methods to pass a connection, but if I am not wrong, you already have to build a connection in those callers.
I would suggest you to use local variable for connection together with "using" since .NET SQL provider will do connection pooling for you and "using" will ensure that your connection is properly closed and disposed. So your code will look like:
decimal GetTotalMaterialCost()
{
decimal total = 0;
using (var con = new SqlConnection(/*connection string if not configured via web.config*/))
{
con.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = con;
cmd.CommandText =
"SELECT SUM(rm.Quantity * m.SellingPrice) AS TotalMaterialCost FROM Resource_Materials rm " +
"JOIN Materials m ON m.MaterialID = rm.MaterialID " +
"JOIN ProjectTasks t ON t.TaskID = rm.TaskID " +
"WHERE t.TaskID=#TaskID HAVING COUNT (*) > 0";
cmd.Parameters.AddWithValue("#TaskID", Request.QueryString["ID"].ToString());
object data = cmd.ExecuteScalar();
if (data == null)
total = 0;
else
total = (decimal)cmd.ExecuteScalar();
}
}
return total;
}
You are calling cmd.ExecuteScalar() twice without resetting it. Your line setting the total variable should be total = (decimal) data;. After all, you already have the answer, why not just use it instead of re-executing the code?