简体   繁体   中英

Correct/Ideal way to manage SQL Connections and Transactions - C#

I have a C# application that makes many SQL calls across multiple functions and classes. The database is SQL Server 2008 R2. Currently each class or function will open it's own SQL connection whenever it needs to read/write data to the database:

using (SqlConnection connection = new SqlConnection(connectionString))

Is this the correct way to handle connection management? Also I am just starting to add transactions, so if I'm not mistaken transactions should be completed on the same connection. Here is an example of some code:

try
{
   Class1 class1 = new Class1();
   class1.data = "somedata";
   class1.save(); // new sql connnection

   Class2 class2 = new Class2();
   class2.data = GetSomeData(); // new sql connection
   class2.save(); // new sql connection
}

catch (Exception e)
{
}

I've looked at TransactionScope and SqlTransaction, but I'm not sure my current connection structure is ideal for this implementation. Any guidance would be greatly appreciated.

"Opening" a new connection for every operation isn't as resource intensive that one might think.

The reason to this is that all ADO.NET providers today uses connection pooling internally. That means that every time you .Close() a connection it's really just returned to the pool.

The performance hit comes when you start to involve more than one connection in a transactions since that means that the transaction is elevated to a distributed transaction. That is, a third party transaction manager is involved and take control of the transaction.

So the answer is that as long as your entities are without dependencies there is no reason to start with transactions or stop using multiple connections.

When are transactions required?

However, if entity A is dependent of entity B you have to use transactions.

The dependencies can be specified by business rules too. Let's take an example.

You have a bank transfer where money should be withdrawn from account A and be deposited to account B. Without a transaction money might be withdrawn from account A but not be deposited to B (due to an error).

You can enclose both save calls inside a using clause which starts a transaction.

whenever your system wants to start a connection, it will inspect parent transactions if there are any.

checkout samples at http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx

At the very least create a data access class that handles persistence of your objects--just pass the object into a class method that knows how to handle it. Spreading the persistence code throughout classes only makes sense if the class is an isolated entity, which most probably are not (most objects interact with other objects). You should use the ORM features available in .NET--SQLMetal (command line) or LINQ-to-SQL ORM designer in Visual Studio. Then you wouldn't have the problems you are encountering now, and could instead focus on what you are really trying to do with your code.

Yes, having the using clause within the same code block that performs the actual marshaling of data between your objects and SQL server is the correct way. The reason is simply that if an error occurs then you aren't leaking connections which could cause other very difficutl to locate issues.

The question is really whether you should have a save call on each individual class or whether you should use something like a data access provider to handle the communications with the database server.

If Entity B has a dependency on Entity A, meaning A must be saved and an ID returned before B can properly save then you have a choice. Either A needs to have a reference to B and handle it's save OR you pass both objects to a data access class which handles the proper saving. An example here would be if Entity A was a order header and B was a line item. In this situation A should have a reference to a collection of B. When A.Save() is called, then it should iterate that collection and call B.Save() itself.

Either way would make it fairly easy to implement transactions within the context of a single connection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM