Access database connection session state - c#

What is wrong with this code ? how to detect the session state, code given below does not work as expected?
OleDbCommand cmd4 = new OleDbCommand(sql4, conn4);
if (conn4.State == ConnectionState.Open) {
conn4.Close();
}
conn4.Open();

Connections implement IDisposeable. For Disposeables I have one rule:
"Never split up the creation and disposing of anything Disposeable. Create. Use. Dispose. All in the same piece of code, ideally using the using block."
There are some really rare exceptions like Logfiles, but a Database is not suiteable for any of those uses anyway (it has too many things that can go wrong on top of the issues files experience).

Related

mysql connector in a multi-threaded environment

I have a c# server that is connecting to a mysql server for data. This c# server is a backend server for a game, that has an open thread for every player currently logged in. How do I go about doing the mysql connection, an open connection for each thread? A single connection using locking for all threads?
I read somewhere that there is a 'threadpool' for this. Is that true? If so, is this the proper way to use it:
using(var conn = new MySqlConnection(DatabaseHelper.getConnectionString()))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT username FROM characters WHERE id=1";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
user = reader.GetString("username");
}
}
}
I think you are confusing two different resources here; you may indeed want an open thread (effectively a process) for each player logged on, but this doesn't mean you should have a connection to the database open for each player constantly, as things like database connections, file handles etc are not managed resources and should be freed up as soon as you are finished with them.
There's a good introduction and explanation of C# threading here.
You should only open a connection to the database when you need it. This means your data access classes could be instantiated many times (this is the simplest design) each with their own connection. If you use connection pooling, which I feel you actually might have been asking about, then you'll benefit further. Moving towards a static database connection design (where many people share the same dao classes) can be much more problematic as you may have to synchronize certain resources, ensure certain variables can only be accessed in sequence via locking or similar, and more.
You can read more about this here for example. Microsoft also talk about the benefits of connection pooling here.
The code you have above is a good starting point for connecting to the database, by including the using statement you are closing and disposing of the connection as soon as you are finished with it; you might also consider the following improvements:
using(var conn = new MySqlConnection(DatabaseHelper.getConnectionString()))
{
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandType = CommandType.Text;
//Parameterize your queries!
cmd.CommandText = "SELECT username FROM characters WHERE id=?"; //Use ? as placeholder for parameters, and add parameters in the order they appear in your query.
cmd.Parameters.Add(new MySqlParameter("#userid", MySqlDbType.Int, userid));
using(IDataReader reader = cmd.ExecuteReader())
{
//You should only expect one record. You might want to test for more than 1 record.
if (reader.Read())
{
user = reader.GetString(reader.GetOrdinal("username")); //Think also about null value checking.
}
}
}
}
You might have a DAO class, or a method on a user class to do this. For example, if it was a method on user, you might do something like:
User myUser = new User(7);
myUser.Load();
Inside of Load, one of the methods you might call is PopulateFromDB() which would contain the code above, and would load all of the properties of this user. You might also have a DAO class that does the same thing:
UserLoader loader = new UserLoader();
string userName = loader.GetUserName(int userId);
which would return the username using the code in the example above. I'd prefer this method to be on a class like User as it's logically connected to it. However, you then run the risk of mixing the DAO logic with the user business logic, which is a topic all on it's own.
Rather than write a lot of this data access logic, you might consider looking at some form of framework like an ORM or similar - this question has already been answered for MySql on SO. This could also save you a lot of time and effort, and will allow you to concentrate on design.

Why does SqlConnection forget the database type

I recently posted (and promptly deleted, when I decided the question was irrelevant to the actual problem) a question about SqlConnection losing its Database information when the scope of "ChangeDatabase" ends. Example:
//Other code...
dbConn = new SqlConnection(dbConnBuilder.ConnectionString);
dbConn.Open();
dbConn.ChangeDatabase(currentDatabase);
dbConn.Close();
}
My questions:
Is it considered bad practice to hold onto a SqlConnection object and open and close it whenever you need it when you'll only ever have ONE connection of a given type?
Why does dbConn.Database not remember currentDatabase after ChangeDatabase (a method not a variable) 'Goes out of scope'? (Heck, I didn't know methods like ChangeDatabase could know about scope).
My connection string was:
Data Source=server.name.com;Persist Security Info=True;User ID=username;Password=password
Thanks guys, let me know if I can give you more information, still learning to use S.O.
Calling Close() completely destroys the object, so you should not be reading any of its properties after.
In fact, there should even be an "after" because you shouldn't be calling Close(). Instead, instantiate the connection in a using block, so that it'll call Dispose(), which does the same thing as Close(), but is guaranteed to do so no matter how you leave the block.
So just make sure to call changedatabase every time you need to execute a statement :-)

using transactions in csla and manual transactionscope

So hopefully with some CSLA skills out there can help me see a better way with this one. I have a situation where I want to manually create my transaction from outside the object and set my transactionAttribute to manual.
So I have some code that looks like this:
using (SqlConnection conn ConnectionManager<SqlConnection>.GetManager("Db").Connection)
{
connectionTransaction = conn.BeginTransaction();
objectRef = objectRef.Save();
//other logic here
objectRef = objectRef.Save();
connectionTransaction.Commit();
}
Then inside the save method there is something like this for the data access:
using (var conn = ConnectionManager<SqlConnection>.GetManager("Db").Connection)
{
using (var cm = conn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandText = "Proc_Name";
// param definitions
cm.ExecuteNonQuery();
}
}
When I do this I receive the following error:
ExecuteNonQuery requires the command to have a transaction when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized.
Ok so that makes sense what it is saying and I could easily fix by assigning the transaction to the command. But I'm wondering if this is actually structured correctly according to CSLA best practices. I can't seem to find a good example in the book I recently got.
I just can't imagine that it is good practice to tell my domain object code to behave like it is in a transaction when there could be times when it isn't.
Can anyone show me the light on what I need to do to fix this correctly?
Ok so there were a lot of things I needed to change with this. But one of the glaring problems with this situation is that I have the connection being used in the using statement. Which as soon as it exits out it is being disposed of. Since this transaction goes through several of these methods like this it turned out my connection and transaction were being disposed of after the first call.
I just had one of those duh moments right now and I realized it. I hate how sometimes the answer can be so obvious.

When using auto-generated TableAdapters, what is the suggested way to deal with repeated instantiation?

I am using the .xsd dataset thingies (which I hate) to auto-generate TableAdapter classes for some backend code.
I have not really used these before, tending to favour manual commands and stored procs whenever possible (for various speed-induced reasons: those xsds play hell with dynamic tables and really large amounts of columns), and am finding myself instantiating a TableAdapter in a large number of my methods, so my question is this:
Will the auto-generated code automatically streamline itself so that a full adapter class is not created on an instatiation, and instead share some static data (such as connection information), and if not would it be better for me to have some sort of singleton/static class provider that can give me access to their methods when needed without the overhead of creating a new adapter every time I want to get some information?
Cheers, Ed
If you're concerned about the performance you could always run a benchmark to see what the performance hit, if any, is.
Sorry you didn't find my answer useful.
My point was that while you had received responses they all seemed to be subjective and not based on hard data. So if you had some reason to be concerned that there was a performance hit in your particular application you should measure it.
There is no reason to refactor one area for performance unless there is an actual problem.
I actually tend to instanciate a very low number of adapters (usually only one of each type). I never tried using them as on the stack variables (instantiated when needed), so I never ran into your question, but I understand your concern.
From what I know the aqdapters themselves may be quite heavyweight in instancing, but the real killer is the connection. What I do is I mark the adapter's Connection modifier as Public in the .xsd designer so I can assign the property whatever I need it to use, and maintain a tight grip on the opening and closing of connections:
void Load() {
using (SqlConnection conn = ...) {
conn.Open();
invoicesAdapter.Connection = conn;
customersAdapter.Connection = conn;
invoicesAdapter.Fill(dataSet.Invoices);
customersAdapter.Fill(dataSet.Customers);
}
}
void Save() {
using (SqlConnection conn = ...) {
conn.Open();
invoicesAdapter.Connection = conn;
customersAdapter.Connection = conn;
invoicesAdapter.Update(dataSet);
customersAdapater.Update(dataSet);
}
}
I ommitted transaction control and error handling for brevity.

How to safely and effectively cache ADO.NET commands?

I want to use this pattern:
SqlCommand com = new SqlCommand(sql, con);
com.CommandType = CommandType.StoredProcedure;//um
com.CommandTimeout = 120;
//com.Connection = con; //EDIT: per suggestions below
SqlParameter par;
par = new SqlParameter("#id", SqlDbType.Int);
par.Direction = ParameterDirection.Input;
com.Parameters.Add(par);
HttpContext.Current.Cache["mycommand"] = com;
Obviously I don't want to run into odd problems like person A retrieving this from the cache, updating param1, person 2 getting it from the cache and updating param2 and each user running the command with a blend of the two.
And cloning the command taken out of the cache is likely more expensive that creating a new one from scratch.
How thread safe is the ASP.NET Cache? Am I missing any other potential pitfalls? Would this technique work for parameterless commands despite threading issues?
Clarefication: If I want to metaphorically shoot myself in the foot, how do I aim? Is there a way to lock access to objects in the cache so that access is serialized?
Quite simply: don't. If you can't see that this is wrong, you need to read up more on ADO.NET. There is plenty of literature that explains the right way to do it: just create connections and commands when you need them, and make sure you dispose them properly.
The Cache itself is thread-safe but that doesn't confer thread-safety on the objects that you place within it. The SqlCommand object is not Thread-safe and therefore not the sort of thing you would want to cache.
The most important thing in this scenario is the caching of the connection which is handled for you and you should not attempt to look after this yourself.
The creation of command object (even one with many parameters) is still going to be peanuts compared with its execution. Unless you have evidence to the contray do not attempt to cache them.
The biggest risk to your project is premature optimisation.
As others have stated, this is just an all around bad idea. There are a number of reasons why it is a bad idea.
More than anything, if you are in a high load situation, storing the command for each and every user is going to really quickly fill up the cache, and depending on priorities, etc, will start to cause other items to fall out of the cache, that should REALLY still be there.
With ADO.NET you really should be creating, using, then disposing of your commands and connections as you use them. Performance wise I have NEVER had to change this system.....and I have not really heard of many others that have as well.
Also, as others mentioned with your code sample, the connection, which is needed to actually execute would be lost anyway.
Why would you ever cache the command? The overhead on the creation of a command is minuscule-you're just newing up a couple of objects and setting some properties. I can't ever see that being a bottleneck..
You want to cache the results of the command, as actually executing the command is (relatively) expensive. And, iin general, you want to treat shared cache as readonly so that you don't have to worry about locking and synchronizing access. Caching the results achieves that.
I should have asked how to lock an item in ASP.NET cache, instead of saying what I was intending to put in the cache.
lock(Cache)
{
// do something with cache that otherwise wouldn't be threadsafe
}
Reference: http://www.codeguru.com/csharp/.net/net_asp/article.php/c5363
Cache your results, and only create the connection (and command) if the resultcache is null:
PsuedoCode:
result = getResultFromCache(CacheKey)
if (result == null)
{
result = getResultFromDB();
InsertIntoCache(result,cacheKey);
}
return result;

Categories

Resources