How to disable connection pool? - c#

Connection string that my app is using to connect to DB is the following:
private const string oradb = "Data Source=(DESCRIPTION=(ADDRESS_LIST="
+ "(ADDRESS=(PROTOCOL=TCP)(HOST=host.name)(PORT=1521)))"
+ "(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=service.name)));"
+ "User Id=myusername;Password=mypass;";
In all DB access points of my app I am using the following pattern:
OracleConnection conn = new OracleConnection(oradb);
try
{
Console.WriteLine("Opening DB Connection...");
conn.Open();
string queryString = string.Format(#"SELECT ...");
using (OracleCommand command = new OracleCommand(queryString, conn))
{
using (OracleDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
...
}
}
}
}
catch (Exception e)
{
Console.WriteLine("Exception occured during DB access: {0}", e.Message);
dbr.Error = e.Message;
}
finally
{
Console.WriteLine("Closing DB connection");
conn.Close();
conn.Dispose();
}
For sure I am properly handling exceptions and in try/catch/finally closing AND disposing connection object. However, often I am receiving oracle service message that I am holding oracle sessions. Moreover, if I just leave my app open and next day try to make operation, I am getting ora-12537 network session end of file exception first time, then second attempt is going through. After some reading it looks like I have to disable connection pool. If this is the right way to solve, how to disable pool? If not, then what other thing can be wrong?

You could add Pooling=False in the connection string, but this means a new connection is created each time.
+ "User Id=myusername;Password=mypass;Pooling=False;";
Take a look at this article, it might help with your issue. Also, take a look at this website page, specifically the Using Connection Pooling section

Related

WinFormApp won't connect to the database

No clue why this won't work. It has worked before.
I do have the connection string in the app.config as well. I get the MySqlException error saying unable to connect to any database.
I made sure the firewall wasn't stopping it and I opened the ports on my router. All the references are in place too. This should work.
string connString = ConfigurationManager.ConnectionStrings["connString"].ConnectionString;
try
{
using (MySqlConnection Conn = new MySqlConnection(connString))
Conn.Open();
MessageBox.Show("DB Connected");
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message);
}
try this code
string connetionString = null;
MySqlConnection cnn ;
connetionString = "server=localhost;database=testDB;uid=root;pwd=abc123;";
cnn = new MySqlConnection(connetionString);
try
{
cnn.Open();
MessageBox.Show ("Connection Open ! ");
cnn.Close();
}
catch (Exception ex)
{
MessageBox.Show("Can not open connection ! ");
}
MySQL Databases cannot be used in WinFormApp due to security risks on a remote server. MS SQL DB's are supported. I didn't know that and I see a lot of questions about this so if anyone can't connect this may be why.

Using or Dispose of SqlConnection not working, but Close does?

I have read the numerous posts on why you should give the using statement preference over manually doing .Open() then .Close() and finally .Dispose().
When I initially wrote my code, I had something like this:
private static void doIt(string strConnectionString, string strUsername)
{
SqlConnection conn = new SqlConnection(strConnectionString);
try
{
conn.Open();
string strSqlCommandText = $"CREATE USER {strUsername} for LOGIN {strUsername} WITH DEFAULT SCHEMA = [dbo];";
SqlCommand sqlCommand = new SqlCommand(strSqlCommandText, conn);
var sqlNonReader = sqlCommand.ExecuteNonQuery();
if (sqlNonReader == -1) Utility.Notify($"User Added: {strUsername}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
conn.Close();
conn.Dispose();
}
}
and this works... no problem. but only ONCE.
so, if I do something like this:
private static void doItLots(string strConnectionString, string strUsername)
{
for(int i=0; i<10; i++)
{
doIt(strConnectionString, $"{strUsername}_{i}");
}
}
it works the FIRST time when i=0, but any subsequent iterations fail with Cannot open database "myDbName" requested by the login. The login failed.
However, if I go back and comment out the conn.Dispose(); line, then it works fine on all iterations.
The problem is simply that if I want to do the .Dispose() part outside of the method, then I am forced to pass a SqlConnection object instead of simply passing the credentials, potentially making my code a bit less portable and then I need to keep the connection around longer as well. I was always under the impression that you want to open and close connections quickly but clearly I'm misunderstanding the way the .Dispose() command works.
As I stated at the outset, I also tried doing this with using like this...
private static void doIt(string strConnectionString, string strUsername)
{
using (SqlConnection conn = new SqlConnection(strConnectionString))
{
try
{
conn.Open();
string strSqlCommandText = $"CREATE USER {strUsername} for LOGIN {strUsername} WITH DEFAULT SCHEMA = [dbo];";
SqlCommand sqlCommand = new SqlCommand(strSqlCommandText, conn);
var sqlNonReader = sqlCommand.ExecuteNonQuery();
if (sqlNonReader == -1) Utility.Notify($"User Added: {strUsername}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
conn.Close();
}
}
}
and this does the exact same thing as the initial code with .Dispose() called manually.
Any help here would be greatly appreciated. I'd love to convert to the using statements but having trouble figuring out how to write reusable methods that way...
UPDATE:
I have narrowed it down a bit. The issue is NOT the iterations or making the calls over-and-over again. But I am still getting an access error. Here is the code:
string strConnectionString = $#"Data Source={StrSqlServerDataSource};Initial Catalog={StrDatabaseName};User id={StrSqlServerMasterUser};Password={StrSqlServerMasterPassword}";
using (SqlConnection connUserDb = new SqlConnection(strConnectionString))
{
try
{
Utility.Notify($"Connection State: {connUserDb.State.ToString()}"); // Responds as 'Closed'
connUserDb.Open(); // <-- throws error
Utility.Notify($"Connection State: {connUserDb.State.ToString()}");
Utility.Notify($"MSSQL Connection Open... Adding User '{strUsername}' to Database: '{strDatabaseName}'");
string sqlCommandText =
//$#"USE {StrDatabaseName}; " +
$#"CREATE USER [{strUsername}] FOR LOGIN [{strUsername}] WITH DEFAULT_SCHEMA = [dbo]; " +
$#"ALTER ROLE [db_datareader] ADD MEMBER [{strUsername}]; " +
$#"ALTER ROLE [db_datawriter] ADD MEMBER [{strUsername}]; " +
$#"ALTER ROLE [db_ddladmin] ADD MEMBER [{strUsername}]; ";
using (SqlCommand sqlCommand = new SqlCommand(sqlCommandText, connUserDb))
{
var sqlNonReader = sqlCommand.ExecuteNonQuery();
if (sqlNonReader == -1) Utility.Notify($"User Added: {strUsername} ({sqlNonReader})");
}
result = true;
}
catch (Exception ex)
{
Utility.Notify($"Creating User and Updating Roles Failed: {ex.Message}", Priority.High);
}
finally
{
connUserDb.Close();
Utility.Notify($"MSSQL Connection Closed");
}
}
return result;
}
The error I am getting here is: Cannot open database requested by the login. The login failed.
One clue I have is that prior to this, I was running this same code with two changes:
1) uncommented the USE statement in the sqlCommandText
2) connected to the Master database instead
When I did that, it didn't work either, and instead I got this error: The server principal is not able to access the database under the current security context.
If I go into SSMS and review the MasterUser they are listed as db_owner and I can perform any activities I want, including running the command included in the code above.
I rewrote all the code to make use of a single connection per the recommendations here. After running into the "server principal" error, I added one more connection to attempt to directly connect to this database rather than the master.
UPDATE 2:
Here is another plot twist...
This is working from my local computer fine (now). But, not (always) working when run from an Azure Webjob that targets an Amazon Web Services (AWS) Relational Database Server (RDS) running MSSQL.
I will have to audit the git commits tomorrow, but as of 5p today, it was working on BOTH local and Azure. After the last update, I was able to test local and get it to work, but when run on Azure Webjob it failed as outlined above.
SqlConnection implements IDisposable. You don't call dispose or close.
try{
using (SqlConnection conn = new SqlConnection(strConnectionString))
{
conn.Open();
string strSqlCommandText = $"CREATE USER {strUsername} for LOGIN {strUsername} WITH DEFAULT SCHEMA = [dbo];";
SqlCommand sqlCommand = new SqlCommand(strSqlCommandText, conn);
var sqlNonReader = sqlCommand.ExecuteNonQuery();
if (sqlNonReader == -1) Utility.Notify($"User Added: {strUsername}");
}}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}

Connect and insert data from my computer to server's MySQL DB table with the help of C#.NET

I want to connect with a server's MySql DB(cpanel) . Though there are no errors every time I'm getting a message for Messegebox : unable to connect to any of the specified any of the MySql hosts.
using MySql.Data.MySqlClient;
connString = "SERVER = ********;PORT=3306;DATABASE=********;UID=**********;PASSWORD=*********";
try
{
conn = new MySqlConnection();
conn.ConnectionString = connString;
conn.Open();
MessageBox.Show("Server is online");
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{ MessageBox.Show(ex.Message);}
If you try to connect to your MySQL server externally, external connections need to be enabled.
Be aware that it is a security hole if you provide your app to others which contain the DB information. To go around that, you need to create a Web-API.
The first step to connect to your app to a remote server MySql Server is verify if it allows external connections, for default the root user is locked, to allow local you can try to connect with the root user typing the following command in MySql:
GRANT ALL PRIVILEGES ON *.* TO 'root'#'%' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH PRIVILEGES;
'root': You can change it with your user.
'%': allows all connections, you can limit it typing an IP.
Second step is verify your MySql .net connector
Cheers!
I would look into using ConnectionStringBuilder. Also note the use of 'using'. This will ensure resources are disposed once finished with.
private MySqlConnectionStringBuilder sConnString = new MySqlConnectionStringBuilder
{
Server = "",
UserID = "",
Password = "",
Database = ""
};
private void Test(){
// open connection to db
using (MySqlConnection conn = new MySqlConnection(sConnString.ToString()))
{
using (MySqlCommand cmd = conn.CreateCommand())
{
try
{
conn.Open();
cmd.CommandText = "SELECT * FROM foo WHERE OrderID = #OrderID";
// Add any params
cmd.Parameters.AddWithValue("#OrderID", "1111");
cmd.Prepare();
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
return;
}
}
}
}

MySQL .Net connection pool connection.Open() very slow

Version 6.4.4:
Using the most basic implementation of MySqlConnection, the following code takes 2-5 seconds per connection when preloading the connection pool to reach the "Min Pool Size" configured in my connection string.
Any ideas why it is taking so long, how to fix, or workarounds?
Connection String:
<add name="users" connectionString="server=192.168.1.2;User Id=dbuser;password=dbpassword;database=users;Pooling=true;Min Pool Size=10;Max Pool Size=50;Persist Security Info=True;" />
Code
private static void MySqlConnectionTester()
{
string connectionString = ConfigurationManager.ConnectionStrings["users"].ConnectionString;
using (var connection = new MySqlConnection(connectionString))
{
using (var command = connection.CreateCommand())
{
command.CommandText = "select * from users;";
try
{
connection.Open(); // This line hangs until "Min Pool Size" is reached.
using (var reader = command.ExecuteReader())
{
while(reader.Read())
{
// Read results
}
}
}
catch(Exception ex)
{
// Log exception
}
finally
{
connection.Close();
}
}
}
}
At MySQL's homepage they write that you should avoid creating, opening and closing the connection object youself, instead you should use the helper class which should work better with connectionpooling.
I have not tested it, but was something I just read :)
The issue was also present on our side with MySql Connector .Net 6.6.5. The MySql Connector .Net 6.8.3 is solving this issue.
Fabrice

Sqlite database locked

I'm using asp.net c# and upload a SqLite database to a server and then I do some inserting and updating. The problem is that sometimes (I think it's when somethings go wrong with the updating or so) the database gets locked. So the next time I try to upload a file again it's locked and I get an error saying "The process cannot access the file because it is being used by another process". Maybe the database file isn't disposed if something goes wrong during the transaction? The only thing to solve this problem is restarting the server.
How can I solve it in my code so I can be sure it's always unlocked even if something goes wrong?
This is my code:
try
{
string filepath = Server.MapPath("~/files/db.sql");
//Gets the file and save it on the server
((HttpPostedFile)HttpContext.Current.Request.Files["sqlitedb"]).SaveAs(filepath);
//Open the database
SQLiteConnection conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;");
conn.Open();
SQLiteCommand cmd = new SQLiteCommand(conn);
using (SQLiteTransaction transaction = conn.BeginTransaction())
{
using (cmd)
{
//Here I do some stuff to the database, update, insert etc
}
transaction.Commit();
}
conn.Close();
cmd.Dispose();
}
catch (Exception exp)
{
//Error
}
You could try placing the Connection in a using block as well, or calling Dispose on it:
//Open the database
using (SQLiteConnection conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;")) {
conn.Open();
using (SQLiteCommand cmd = new SQLiteCommand(conn)) {
using (SQLiteTransaction transaction = conn.BeginTransaction()) {
//Here I do some stuff to the database, update, insert etc
transaction.Commit();
}
}
}
This will ensure that you're disposing of the connection object's correctly (you're not at the moment, only closing it).
Wrapping them in using blocks ensures that Dispose is called even if an exception happens - it's effectively the same as writing:
// Create connection, command, etc objects.
SQLiteConnection conn;
try {
conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;");
// Do Stuff here...
}
catch (exception e) {
// Although there are arguments to say don't catch generic exceptions,
// but instead catch each explicit exception you can handle.
}
finally {
// Check for null, and if not, close and dispose
if (null != conn)
conn.Dispose();
}
The code in the finally block is going to be called regardless of the exception, and helps you clean up.
An asp.net application is multithreaded in the server.
You can't do simultaneous writing (insert, select, update...) because the whole db is locked. Simultaneously selecting is allowed when no writing is happening.
You should use the .NET ReaderWriterLock class: http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx
Shouldn't you do cmd.Dispose() before conn.Close()? I don't know if it makes any difference, but you generally want to clean things up in the opposite of initialization order.
In short, SQLite handles unmanaged resources slightly differently than other providers. You'll have to explicitly dispose the command (which seems to work even if you are working with the reader outside of the using() block.
Read this thread for more flavor:
http://sqlite.phxsoftware.com/forums/p/909/4164.aspx

Categories

Resources