I have the following INSERT method in a C# web project. If I run the project without MySQL connection poling everything works fine, but when I activate Pooling=True in the DB connection string this method stops working, the insert statements never complete.
I realized how to modify the code to make it work, but I would like to understand what is happening and I hope you could help.
When I comment line //myR.Close(); everything works fine.
using MySql.Data.MySqlClient;
//query example consulta="INSERT INTO users (id, name) VALUES (1, 'Rob');
public static MySqlConnection GetWriteConnection()
{
string connStr = MySqlConnectionStrings.WriteConnectionString;
MySqlConnection conn = new MySqlConnection(connStr);
return conn;
}
public static MySqlConnection GetReadConnection()
{
string connStr = MySqlConnectionStrings.ReadConnectionString;
MySqlConnection conn = new MySqlConnection(connStr);
return conn;
}
public static bool Insert(string consulta)
{
MySqlConnection conn = BdaHelper.GetWriteConnection();
conn.Open();
using (conn)
{
try
{
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
MySqlCommand micomando = new MySqlCommand(consulta, conn);
micomando.ExecuteNonQuery(); //still not working
return true;
}
catch (Exception ex)
{
return false;
}
}
}
My app has also multi-thread concurrency and two types of database connections, one specifically for only-read purposes and other different for write. When an insert statement fails I don't get any error simply the change doesn't commit in the database. Reading the article in the comments I don't think this applies to this issue but I would add an example of my main program:
MySqlConnection readConnection = BdaHelper.GetReadConnection();
using (readConnection)
{
var users = GetUsers(readConnection);
var credentials = GetCredentials(readConnection);
//Example is the query that fails don't giving any exception
Insert("INSERT INTO login_log (id_user, date) VALUES (1, now())");
}
May the problem be caused because there are two concurrent connections?
I shouldn't reuse read connection, even is a different connection than the write connection?
Related
EDIT: I've just tested it in ASP.NET and it works perfectly fine. So no issue with the connection string or anything. Guess Unity doesn't like this method? Maybe there's some more DLL's I need to copy? Any ideas?
So I'm making a game in Unity and I'm trying to use the System.Data.SqlClient library to connect to some stored procedures I have made for things such as registering a user.
I have copied the System.Data.dll from "C:\Program Files\Unity\Editor\Data\Mono\lib\mono\unity" and that has all worked fine.
I'm currently using this connection string, which works fine on an ASP.NET application but just using a different mdf:
private string connectionString = #"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename='C:\Users\uppy8\Desktop\Computer Science Project\Mining Game\Assets\MineRace.mdf';Integrated Security = True";
The problem occurs when running this code:
using System.Data.SqlClient;
using System.IO;
public void Login()
{
Crypto crypto = new Crypto();
using (SqlConnection conn = new SqlConnection(connectionString))
{
try
{
conn.Open();
} catch (Exception e)
{
Debug.Log(e);
}
SqlCommand command = new SqlCommand("USERS_LOGIN_USER", conn);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#Username", usernameInputField.text));
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
if (crypto.EncryptString(passwordInputField.text) == reader["password"].ToString())
{
UserAccountManager.instance.userInfo = FetchUserInfo((int)reader["id"]);
}
}
}
}
The problem happens on the line "conn.Open()", where Unity gives me the error:
System.Net.Sockets.SocketException: No such host is known.
Furthermore, without the try catch, the error occurs where I create a new SqlDataReader, where I get this issue:
InvalidOperationException: ExecuteReader requires an open connection to continue. This connection is closed.
I understand that this is an issue with the connection, in that it's not running or the connection isn't working properly, however I can't seem to find a solution and I have a sneaky suspicion that it's something to do with Unity not supporting this library.
Some more clarification just before I end off:
The user enters their credentials into the "usernameInputField" and "passwordInputField"
The user presses Login, which runs the "Login" method shown above
The error occurs.
If any more information is required please leave a comment.
Thanks!
What is the scope of connectionString? Do you need to pass the connectionString to the Login() function?
public void Login(string connectionString)
I am a DBA, not a .Net developer, so forgive me if my questions are too basic or if my .Net syntax is wrong.
You can try this
string connectionString = #"Data Source = (localdb)\MSSQLLocalDB; Initial Catalog ='C:\USERS\uppy8\Desktop\Computer Science Project\Mining Game\Assets\MineRace.mdf'; Integrated Security = True; Connect Timeout = 30; Encrypt = False; TrustServerCertificate = True; ApplicationIntent = ReadWrite; MultiSubnetFailover = False"
SqlConnection con = new SqlConnection();
if (con.State==ConnectionState.Open)
{
con.Close();
con.ConnectionString = connectionString;
con.Open();
cmd.Connection = con;
}
else
{
con.ConnectionString = connectionString;
con.Open();
cmd.Connection = con;
}
It's really odd. I just use the default connection everything, it is the first time i get this error been trying for hours to fix it and find solution online with no success. I have this code:
class DbConnect
{
//get values of name and customerid using the bracelet id ( a equijoin using customer, ticketpurchase and ticket)
//every ticket is assigned a bracelet id - and i have 6 bracelets to add so also 6 dummy profiles in database
//method to look for customerid using bracelet id and return only one string
public int CustomerId(string braceletId)
{
String str = #"server=localhost;database=dbi340001;userid=xxxxxxxxxxx;password=xxxxxxxxxxxxxxx;";
MySqlConnection con = new MySqlConnection(str);
try
{
con.Open(); //open the connection
MessageBox.Show("welcome");
return 1;
}
catch (MySqlException err) //We will capture and display any MySql errors that will occur
{
Console.WriteLine("Error: " + err.ToString());
}
finally
{
if (con != null)
{
con.Close(); //safely close the connection
}
} //remember to safely close the connection after accessing the database
return 0;
It's a really simple code which i call from another class and i just wrote it to see if the connection will happen with default code. The error is null refference exceptions on conn.isPasswordExpired and conn.ServerThread adn conn.ServerVersion which are all parameters with only get from the mysqlconnection object so it really doesn't make any sence.
Any help would be appreciated!
con.IsPasswordExpired; is called right after MySqlConnection con = null;
Obviously, con is still null when you call con.IsPasswordExpired;
You should consider moving that statement anywhere AFTER con = new MySqlConnection(str);
You should try
MySqlConnection con = new MySqlConnection();
So that it will initialize the object con, then It will not be null.
I used to call several functions with this connection string:
class Solders_DB
{
SqlConnection connection;
SqlCommand query;
String command;
public Solders_DB()
{
connection = new SqlConnection();
connection.ConnectionString = "Server=localhost;Database=Scheduling_Employee ;Trusted_Connection=True;MultipleActiveResultSets=True;";
query = new SqlCommand();
}
As you see I used this MultipleActiveResultSets=True; in my connection but in this function :
command = #"SELECT [GID] FROM [Scheduling_Employee].[dbo].[Solder] where [ID]=#ID";
query.CommandText = command;
query.Parameters.Clear();
query.Parameters.AddWithValue("#ID", id);
Object o= query.ExecuteScalar();
I faced with this error:
There is already an open datareader associated with this command which must be closed first
The code in your question is not complete. Please explain yourself better for further assistance.
When using a SqlConnection is recommended to use the 'using' statement like this:
using (SqlConnection SqlConn = new SqlConnection(ConnString))
{
try
{
SqlConn.Open();
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
return null;
}
}
You're trying to read data from the first execution of your query, please update your question and put the complete code and the error stack.
Its usually when there was another query before that one and has not yet stopped executing inside the database engine (maybe it was a heavy script). You could try query = new SqlCommand();, query.Cancel() or
while(query.Connection.State != System.Data.ConnectionState.Open){ Threading.Sleep(100);}
Im making a few static classes to avoid rewriting the same code multiple times and to keep all the database related methods in the same place.
the class look like this:
public static class Database_dbSurvey
{
public static DataSet GetQuestionari()
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["default_connection"].ConnectionString);
string query = "[admin].[SRV_Categorie_Lista]";
SqlCommand cmd = new SqlCommand(query, connection);
cmd.CommandType = CommandType.StoredProcedure;
//GetDataSet use the SqlDataAdapter.fill() method
return Utils.GetDataSet(cmd);
}
etc.... (others similar methods)
}
I want to reduce the code and I want to make it more "object oriented", so I started by making a property for the SqlConnection (which is the same for every methods of this class).
private static SqlConnection connection
{
get { return new SqlConnection(ConfigurationManager.ConnectionStrings["default_connection"].ConnectionString); }
}
The problem is that it works perfectly with SqlDataAdapter.fill(), till I use a method like this:
using (connection)
{
connection.Open();
cmd.ExecuteNonQuery();
}
Now, the next usage of the connection will throw the "not istanziated" exception and I can't understand why.
what is the correct way to define the connection property?
p.s.
if you have other suggestion on improving the code it will be higly appreciated
EDIT:
I still dont get it why the "new" keyword do not create another istance of the SQLConnection everytime I call it.
however I made some changes to make the code safer:
private static string connection_string
{
get { return ConfigurationManager.ConnectionStrings["Connection_dbPrysmianSurvey"].ConnectionString; }
}
public static DataSet GetQuestionari(string username)
{
string query = "[dbo].[SRV_Test_Lista]";
using (SqlConnection connection = new SqlConnection(connection_string))
using (SqlCommand cmd = new SqlCommand(query, connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#username", username);
return Utils.GetDataSet(cmd);
}
}
public static int CreaTest(string ID_questionario, string username)
{
string query = "[dbo].[srv_test_genera]";
using (SqlConnection connection = new SqlConnection(connection_string))
using (SqlCommand cmd = new SqlCommand(query, connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ID_categoria", ID_questionario);
cmd.Parameters.AddWithValue("#ID_utente", username);
connection.Open();
return (int)cmd.ExecuteScalar();
}
}
But considering the fact that I have 40-50 methods it's still is a pain to rewrite the same lines 40-50 times, any suggestions?
Do not use using keyword in your case.
It will dispose the connection after that using's scope is complete by calling SqlConnection.Dispose method.
using(connection) {...}'s equivalent -
try
{
connection.Open();
cmd.ExecuteNonQuery();
}
catch
{
throw;
}
finally
{
connection.Dispose();
}
As #Parag Meshram mentioned, using keyword disposes everything inside itself when completed.
There are two ways I can suggest:
(1) Don't make connection a static method
private SqlConnection connection() { get { return new
SqlConnection(ConfigurationManager.ConnectionStrings["default_connection"].ConnectionString);}
}
then use it like
SqlConnection newConnection = connection();
using (newConnection) { ... }
Or
(2) Keep your static method as is but use it like this:
try {
connection.Open();
cmd.ExecuteNonQuery(); } catch {
throw; }
This way, your connection is not disposed.
I had the same problem a year ago and that's now I resolved it, using method (2).
I tried to insert some data into my database (sql server/local file) but it doesn't work.
public bool SaveCookie(string cookie, string expires)
{
SimpleDBM db = new SimpleDBM();
db.Connect();
try
{
string query = string.Format("INSERT INTO Cookies(cookie_value, cookie_expires) VALUES('{0}', '{1}');", cookie, expires);
SqlCommand cmd = new SqlCommand();
cmd.CommandText = query;
//...
SqlDataReader data = db.Query(ref cmd);
return data.Read();
}
catch
{
return false;
}
finally
{
db.Close();
}
}
The SimpleDBM class:
public class SimpleDBM {
public static string dbpath = #"...";
public static string dbname = "db.mdf";
public static string dfullPath = Path.Combine(dbpath, dbname);
public static string connStr = string.Format(#"Data Source=.\SQLEXPRESS;AttachDbFilename={0};Integrated Security=True;Connect Timeout=30;User Instance=True", dfullPath);
private SqlConnection con;
public void Connect()
{
con = new SqlConnection();
con.ConnectionString = connStr;
con.Open();
}
public SqlDataReader Query(ref SqlCommand cmd)
{
cmd.Connection = con;
return cmd.ExecuteReader();
}
public void Close()
{
con.Close();
}
}
Can someone point out my mistake? For other queries it seems to work fine.
Thanks in advance.
The problem seems to be that you're trying to execute a query that doesn't return a result set using the ExecuteReader method of the SqlCommand class which will attempt to execute your query and create and return a DataReader for an eventual result set.
You should use ExecuteNonQuery for INSERT and UPDATE sql statements.
SIDE NOTE
Not that it's the reason you're getting the error but you should also consider using SqlParamters instead of composing the values into the INSERT statement. Using prepared SQL statements generally gives a performance enhancement and also helps prevent SQL injection attacks.
For an example of using prepared statements, see the MSDN page or the Prepare method.
You are using a ExecuteReader when you should be using ExecuteNonQuery.
Not related to your error you really should not be using String.Format with SqlCommand. What you should do is
string query = "INSERT INTO Cookies(cookie_value, cookie_expires) VALUES(#cookie, #expires);", cookie, expires);
SqlCommand cmd = new SqlCommand();
cmd.Parameters.AddWithValue("#cookie", cookie);
cmd.Parameters.AddWithValue("#expires", expires);
cmd.CommandText = query;
With your method ask your self if someone passed a cookie of ' ''); Drop table Cookies --? This is called a "Sql Injection Attack" and is one of the top 5 reasons websites get hacked.
EDIT
Just to help give another example of why using String.Format to pass values you did not generate is bad.