Should I keep the SqlConnection open? - c#

In my Unity3D game the Player plays himself through short levels, which at the beginning take about 4 seconds. The goal is to get the best possible clear time in each level. I am currently saving these clear times locally, but I would like to upload them to an SQL Server, to be able to create a leaderboard for each level.
Since performing the SqlConnection.Open() command takes about 1-2 seconds, sometimes also 3, I was wondering whether I should keep a static connection always open, ready to execute any queries that I want to run.
Are there any unwanted and dangerous side-effects when doing it?
Edit: This is the code that I use for opening the SqlConnection.
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder()
{
DataSource = dataServer,
UserID = userId,
Password = password
};
SqlConnection connection = new SqlConnection(builder.ToString());
connection.Open();

First I'll answer this question:
Are there any unwanted and dangerous side-effects when doing it?
Assuming you keep this code in your Game (client) and the SQL Server is not client-side but in a server of yours located somewhere, a simple Client Reverse Engineer will be able to grab your credentials from your connection string and use them to gain Unauthorized access to your database. (NEVER trust the client)
With that being said, I would suggest you use a simple server-side technology (php,Socket App, Java servlet, etc..) along with the SQL that the client will send the information there and then to the database.
Example:
1) Client-> Posts Data -> PHP
2) PHP -> Connects -> SQL Database
3) PHP -> Inserts data -> SQL Database
Like this you can also retrieve the results of your ladder from the database by asking php (or whatever technology you are using) to send your data to the client.
Best wishes in your progress, and feel free to contact me for any additional information!

Related

Extremely slow mysql connection establishment only when called from code

I am currently trying to do something that should be simple and straight-forward - connect to a database server, run a query, see if I get anything back and if so send it back to the user. This is the code I'm using to do it:
MySqlDataReader reader = MySqlHeaper.ExecuteReader(connectionString, $"SELECT * FROM table WHERE insertDateTime > '{DateTime.Now.AddSeconds(-1800).ToString("yyyy-MM-ddTHH:mm:ss")}'";
I have also tried this with a MySqlCommand and MySqlConnection object pair, and either way the result is the same - it takes approximately 7100ms to connect to the MySql server. I know that sounds like a problem that should be on ServerFault, but my testing tells me otherwise. When I use the command line MySql client to connect to my database server using exactly the same credentials and run exactly the same query I get my connection established and my data back in nothing flat. I don't know at this stage if it's a server setting or not, but here's what I've tried so far:
Rebooting the server
Restarting the MySQL server
Setting the skip_name_resolve setting to 1 in order to prevent reverse name lookups on connect
Using alternative means of querying the server (mysql command line client and MySQL Workbench)
Opening all AWS IAM permissions on the RDS instance to allow everything from the server
Nothing seems to be making any difference, so I'm at a loss to explain this terrible performance. It's also only happening when I open the connection. Running queries, inserts, what have you is lightning fast. Any suggestions anyone might have would be most helpful.
I would not expect IAM permissions to have any impact on performance. I would expect them to be either successful or not successful.
I would execute some diagnostic protocols to get more information.
1) Try a subsequent query, to see if it is an issue with the stack being initialized. Are subsequent queries faster?
2) Try a query that is just an identity query. Something that doesn't require any sort of IO.
3) Try a query from a different platform (maybe a scripting language like ruby or php)
Once you answer those it should help you narrow it down.
This is most likely caused by Connector/NET executing a slow WMI query to query connection attributes when opening the connection; this is logged as MySQL bug 80030.
As far as I know, this isn't fixed in newer versions of the driver, but you can work around it by switching to MySqlConnector, an OSS MySQL ADO.NET library.

Open a sage 300 AccPac DBLink Connection to a session

I am trying to write c# code around opening a Sage 300 Connection using C#. I am using the Acccpac.Advantage DLL.
Here is my code
try
{
sage300Session.Init(sessionHandle, appID, programName, appVersion);
sage300Session.Open(_user, _ppswd, _companyID, DateTime.Today, 0);
// Open a database link.
sage300DbLink = sage300Session.OpenDBLink(DBLinkType.Company, DBLinkFlags.ReadWrite);
}
The issue I am having is, no matter what I put in the password, the call to .Open seems to succeed. If I put an invalid user or companyID, I get errors as expected. (the connestion status seems to say open either way).
My question is - what is happening with the password that is doesn't seem to be used and 2- when I am through with what I am doing, is there a way to correctly close the connection?
The Accpac.Advantage dll is v 2.0.50727 and I am connecting to Sage 300 2014 environment.
As it turned out, the security setting was not enabled in the system database to require passwords to log in. Setting that "resolved" the issue and made the password be used. I never did find a way to disconnect from the session so I let it disconnect when I am done with the processing by having the connection go out of scope
Actually, both Session and DBLink implement IDisposable and calling .Dispose (or the using keyword) would be enough to end the session. (I would have wanted to add this as a comment, but couldn't).

Access denied for user 'root'#'localhost' (using password: YES) in Visual Studio

Kindly bear with me. I am a Microsoft SQL Server person with loads of Visual Studio experience, but I need to get something done using a MySQL database.
I am trying to create a little tool here that will allow our developers to quickly update database records, and I am using Visual Studio to create a small Windows Form to do this.
In a Microsoft SQL Server connection string, I could write something like this:
Server=myServerAddress;Database=myDataBase;User Id=username;Password=password;
In a MySQL connection string, there appear to be multiple other options, but the first one looks basically the same:
Server=myServerAddress;Database=myDataBase;Uid=username;Pwd=password;
When I attempt to open the MySQL connection from my PC, I get the exception listed in the title (actually, it shows the Uid value and the IP Address of my PC instead of localhost, but I am hoping more people will recognize the error easier this way):
public static void MySQLi_Connect() {
m_err = null;
var str = Properties.Settings.Default.ConnStr;
try {
m_conn = new MySqlConnection(Properties.Settings.Default.ConnStr);
m_conn.Open();
} catch (MySqlException err) {
ErrorLog("MySQLi_Connect", err);
}
}
I did a search, and it seems that the Uid on MySQL needs to be granted access from the specific IP Address that the connection is being made from.
Further, I found this on the mysql.com doc pages:
If you do not know the IP address or host name of the machine from which you are connecting, you should put a row with '%' as the Host column value in the user table. After trying to connect from the client machine, use a SELECT USER() query to see how you really did connect. Then change the '%' in the user table row to the actual host name that shows up in the log. Otherwise, your system is left insecure because it permits connections from any host for the given user name.
A few things:
It looks like I can connect to MySQL by using a % setting in the Uid jp2code, but MySQL says I need to change that back right away to remove system vulnerability.
Microsoft SQL Server did not seem to require this - or, if it did, I simply never was slapped in the face with this vulnerability issue like MySQL is doing.
Now, I ask:
If this is going to be a tool used by different developers on different PCs, is it common practice to turn the blind eye to this horrendous system vulnerability?
Is this not really as big of a concern as MySQL is making it appear?
What is the best way to continue with a Windows Forms application that needs to connect from various locations? Obviously, I do not want to continuously be adding more entries for a particular application every time another developer wants to use the tool or someone tries to run it from a different PC.
You can configure the security of your MySQL server as strong as you like, usually you dont connect users but applications. So if you have your root user without password in production environment is your fault. Usually developers have access to development environment, so this is not a big deal.
Of course try to have as many users as roles you need, for your example I think one user is enough. In production use a secure config file for save a secure password and set you mysqlserver restricted.
I was having the same issue and I found out that the password wasn't correct.
GO to your sql command line and type the code below:
mydb in the line below is the name of the database you are working on.
passwd in the line has to match the password you have in c# code so in your case "password"
grant all privileges on mydb.* to myuser#localhost identified by 'passwd';
Like OP says you can wildcard the hostname portion. I used this on our dev-server (not recommended for production servers):
update mysql.user set host = '%' where host='localhost';
Then I had to restart the server to make MySQL use it (propably I could just have restarted the MySQL service).

Generating a Connection String in C#

I'm trying to write an application that will let users connect to an arbitrary database, assuming they have the proper ODBC drivers. However, I'm getting stuck on the connection strings. For any particular database type it's easy to look online and find which keyword/value pairs are required, but is that information accessible from the driver itself?
What I want to do is have the user select the driver they want from a list (generated by SQLDrivers), then generate a form that will prompt them for the keywords necessary to generate the string, so that my application does not need to know about specific ODBC drivers. Is there any way to do this? Or will I have to hard code support for each one separately? Maybe connection strings aren't the way to go, and there's another method I'm overlooking?
You can take a look at ConnectionStringBuilders and see if they'll be any help.
You can use the following code to enumerate the configurable properties, which would allow you to create your config form.
var builder = new SqlConnectionStringBuilder();
var properties = (from key in builder.Keys.OfType<string>()
select key);
properties contains:
Data Source
Failover Partner
AttachDbFilename
Initial Catalog
Integrated Security
Persist Security Info
User ID
Password
Enlist
Pooling
Min Pool Size
Max Pool Size
Asynchronous Processing
Connection Reset
MultipleActiveResultSets
Replication
Connect Timeout
Encrypt
TrustServerCertificate
Load Balance Timeout
Network Library
Packet Size
Type System Version
Application Name
Current Language
Workstation ID
User Instance
Context Connection
Transaction Binding
In 2010 Microsoft released there VS2010 Connection dialog for us little people to use. It is awesome, should do what you want and is freely distributable. The download for the dialog and its source code can be found here.
To get you started: once you have compiled the code you will need to include references to Microsoft.Data.ConnectionUI, Microsoft.Data.ConnectionUI.Dialog and Microsoft.Data.ConnectionUI.SqlCeDataProvider. The dialog is then called like
// Initialisation.
DataConnectionDialog dcd = new DataConnectionDialog();
DataConnectionConfiguration dcs = new DataConnectionConfiguration(null);
dcs.LoadConfiguration(dcd);
// Edit existing connection string.
if (!String.IsNullOrEmpty(strExistingConn))
dcd.ConnectionString = strExistingConn;
// Launch Microsoft's SqlConnection dialog.
string strSqlFinConn = String.Empty;
if (DataConnectionDialog.Show(dcd) == DialogResult.OK)
{
// Load tables as test.
using (SqlConnection connection = new SqlConnection(dcd.ConnectionString))
connection.Open();
}
dcs.SaveConfiguration(dcd);
return dcd.ConnectionString;
If this is not what you want then #HackedByChinese answer looks like the best approach.
I hope this helps.
I found a very simple way to solve this, actually, at http://msdn.microsoft.com/en-us/library/windows/desktop/ms715433(v=vs.85).aspx.
If you call the ODBC API function SQLDriverConnect with an incomplete connection string (like, for example, one that only contains the Driver keyword) and set the last argument to SQL_DRIVER_COMPLETE, it will pop up with a dialog generated by the driver that prompts for any required information that wasn't included, then return the finished connection string once it's closed.
Apart from the good answers already posted you might want to take a look at the ODBC API SQLBrowseConnect.

Is it possible to enforce Read Only behaviour with SqlCommand?

Is it possible to enforce read only permissions using the System.Data.SqlClient code accessing a Sql Server database?
I want to allow trusted users to write their own SELECT statements, in a web site.
NO Im not trolling here! Obvious solutions are to create a readonly user in the database, and use those credentials in the connection string, and surely only an idiot accepts a SQL statement in a webpage. This is a user deployment issue, I don't trust someone else to set that up correctly and don't want to write code to check that the readonly connection string is readonly.
One solution would be to parse the SQL and verify that it is a readonly command, or to do something similar. What I want to do is to do something like;
SqlConnection conn = new SqlConnection(myConnectionString, Flags.Readonly)
update
Given a connection string with SA priviledges, "create user blah with password=xxx" "use my-db" "create login blah" "grant select on mytable to blah". Then make a new connection string.
Create a new login in SQL Server and only give that login the permissions you want on the tables. Then in the connection string have the application use that login. You mention this as an obvious solution in your post but I don't see why you wouldn't want to do it this way.
You could use a transaction and always rollback? (but make sure the executed sql doesn't commit)
No, there is no built-in facility for ensuring that end-user actions don't have side effects. While it may be simple in your scenario, a general-purpose implementation of this would be incredibly complex, if not impossible. What if the select statement uses a UDF that has side effects?
create another database, possibly restore the nightly backup, so it a day old. only allow the users to access this database. Then users can't slow down production with their awful queries or really hurt anything if your security fails and an change is made.

Categories