using transactions in csla and manual transactionscope - c#

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.

Related

Access database connection session state

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).

Reducing number of using in C#

My question might be silly or may not be a question at all, but here it goes..
I am performing quite some database operations in my ASP.net MVC project where I am creating two objects each and every time namely, SqlConnection and SqlCommand.
I have shown an example below
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand command = new SqlCommand("sRegisterUser", connection))
{
I am doing all these different operations inside one class under different methods.
My question is how can I reduce the creation of these objects each and every time? How can I create them globally
PS: sRegisterUser is a stored procedure, like wise other methods use different procedures which gets different values as parameters.
Please help me out.
Thanks for any help in advance.
The answer is, don't. You do not want to share these objects, you are using them appropriately.
You don't. You either keep the object alive, which is bad. Or you dispose it the way you should, and currently do.
So, why do you have use using?
Since using is necessary for disposing the handles in Windows.
You could also write this, which is similar to using using:
SqlConnection connection = new SqlConnection(connectionString);
connection.Close();
connection.Dispose();
using also disposes when the code above throws an error. Using using is actually the shortest way to code this.
So the error-save version should be:
SqlConnection connection;
try
{
connection = new SqlConnection(connectionString);
...
connection.Close();
}
finally
{
connection.Dispose();
}
As others already said, there is nothing wrong with what you're doing right now. ADO.NET objects are meant to be used and disposed of. As a rule of thumb you should create them as late as possible and dispose of them as soon as possible.
With that being said, I understand what you're trying to do here and I do have a few ideas you might be interested in for making your life easier while keeping good programming practices.
If you want to make the code more concise you can chain using statements:
using (var cn = new SqlConnection(yourConnectionString))
using (var cmd = new SqlCommand(yourQuery, cn))
{
// do stuff
}
The IDE will not try to indent the second block, making it easier on you to read.
You can also create an abstraction layer for your procedure:
public static class Procedures
{
public static void RegisterUser() // add whatever parameters you need
{
using (var cn = new SqlConnection(yourConnectionString))
using (var cmd = new SqlCommand(yourQuery, cn))
{
// do stuff
}
}
}
From then on you can execute your procedure simply by calling:
Procedures.RegisterUser();
Another alternative is to introduce a factory pattern to get your objects. This alone won't reduce their number but it might help in getting them all set up already (ie correct connection string).
You also can be creative and combine the two patterns. A custom class implementing IDisposable can take care of creating the necessary ADO objects, open the connection, execute your query, close the connection and dispose of any objects that needs disposal when it is itself disposed of.
Take your pick.

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.

Transaction Scope fails with BeginTransaction in Oracle : Connection is already part of a local or a distributed transaction

Having this strange behavior while using OracleConnection with TransactionScope.
If i try to use connection.BeginTransaction() in a transaction scope i get simple elegant InvalidOperationException : Connection is already part of a local or a distributed transaction.
here is some code:
var trxOptions = new TransactionOptions();
trxOptions.IsolationLevel = IsolationLevel.ReadCommitted;
using (var transaction = new TransactionScope(TransactionScopeOption.Required,trxOptions))
{
var c = ConfigurationManager.ConnectionStrings["oracle_test"].ConnectionString;
using (var oracle = new OracleConnection(c))
{
oracle.Open();
using (var tr = oracle.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
var cmd = oracle.CreateCommand();
cmd.CommandText = "INSERT INTO simple_user VALUES('a')";
cmd.ExecuteNonQuery();
tr.Commit();
}
}
// now go to sql server and insert data
transaction.Complete();
}
If I dont use BeginTransaction everything works. Any ideas to make it work?
PS: I am not having such an issue on Sql Server.
Edit
Thanks for answers i suppose i should add some edit to make my question clear.
First off all, the code i provided above is demonstration of problem. Lets say i have two dll's MyProject.Oracle.dll and MyProject2.MsSql.dll and i want to use methods inside these dll's and they use db.BeginTransaction(). If these dlls had used TransactionScope my outer transaction wouldnt be a problem. Distrubuted transaction would be handled without any issues. But i cannot change code inside dlls.
And why db.BeginTransaction() works for SqlServer but not for Oracle?
I hit the same question in conjunction with NHibernate.
Other answers indicate not to mix TransactionScope and BeginTransaction. Unfortunately no sources to support that claim where added. Here my research:
As stated on MSDN (search for "mix") and in this discussion, one should not mix both concepts, not even for SQL-Server. Why it seems to work for SQL-Server, for both local and distributed transactions, is still not clear to me.
Some seem to think this is a stupid question but it makes sense when seen in context of NHibernate (see here, here and here).
The TransactionScope and DbConnection.BeginTransaction are 2 exclusive ways of transaction management. You use either 1 of them.
The moment you call OracleConnection.Open, the oracle connection is enlisted in the ambient system transaction. All you then need to do is call TransactionScope.Complete(),if you want to commit the transaction or do not call it, in which case the system transaction is rolled back.
In case you do not want to enlist immediately on 'Open', you can set the 'enlist' connection string attribute to 'dynamic' and then enlist explicitly via a call to 'OracleConnection.EnlistTransaction'
The reason it works for SQL/Server and not Oracle is that SQL/Server supports nested transactions and Oracle does not.
You should do some more reading on TransactionScope
First of all the enumeration of TransactionScopeOption
Required:
A transaction is required by the scope. It uses an ambient transaction
if one already exists. Otherwise, it creates a new transaction before
entering the scope. This is the default value.
So the transaction if not available is created and automatically associated.
The ambient transaction is the transaction within which your code executes. You can obtain a reference to the ambient transaction by calling the static Current property of the Transaction class.
You should not use the inner Transaction object, TransactionScope creation already does it and the Complete method does the commit, the inner BeginTransaction and Commit method calls are not needed.
How does it work if you follow this way?

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.

Categories

Resources