passing DB Connection object to methods - c#

Was wondering if it is recomended to pass a database connection object around(to other modules) or let the method (in the other module) take care of setting it up. I am leaning toward letting the method set it up as to not have to check the state of the connection before using it, and just having the caller pass any needed data to the calling method that would be needed to setup the connection.

Personally I like to use tightly scoped connections; open them late, use them, and close them (in a "using" block, all within the local method). Connection pooling will deal with re-using the connection in most cases, so there is no real overhead in this approach.
The main advantage in passing connections used to be so that you could pass the transaction around; however, TransactionScope is a simpler way of sharing a transaction between methods.
Since the classes are implementation specific, I'd write each to open it's own native transaction. Otherwise, you can use the ado.net factory methods to create the appropriate type from the config file (the provider name).

Personally, I like storing a stack of my current open connection and transactions on top of the Thread Local Storage using SetData and GetData. I define a class that manages my connections to the database and allow it to use the dispose pattern. This saves me the need to pass connections and transactions around, which is something that I think clutters and complicates the code.
I would strongly recommend against leaving it up to the methods to open connections every time they need data. It will leads to a really bad situation where it is both hard to manage transactions throughout the application and too many connections are opened and closed (I know about connection pooling, it is still more expensive to look up a connection from the pool than it is to reuse an object)
So I end up having something along these lines (totally untested):
class DatabaseContext : IDisposable {
List<DatabaseContext> currentContexts;
SqlConnection connection;
bool first = false;
DatabaseContext (List<DatabaseContext> contexts)
{
currentContexts = contexts;
if (contexts.Count == 0)
{
connection = new SqlConnection(); // fill in info
connection.Open();
first = true;
}
else
{
connection = contexts.First().connection;
}
contexts.Add(this);
}
static List<DatabaseContext> DatabaseContexts {
get
{
var contexts = CallContext.GetData("contexts") as List<DatabaseContext>;
if (contexts == null)
{
contexts = new List<DatabaseContext>();
CallContext.SetData("contexts", contexts);
}
return contexts;
}
}
public static DatabaseContext GetOpenConnection()
{
return new DatabaseContext(DatabaseContexts);
}
public SqlCommand CreateCommand(string sql)
{
var cmd = new SqlCommand(sql);
cmd.Connection = connection;
return cmd;
}
public void Dispose()
{
if (first)
{
connection.Close();
}
currentContexts.Remove(this);
}
}
void Test()
{
// connection is opened here
using (var ctx = DatabaseContext.GetOpenConnection())
{
using (var cmd = ctx.CreateCommand("select 1"))
{
cmd.ExecuteNonQuery();
}
Test2();
}
// closed after dispose
}
void Test2()
{
// reuse existing connection
using (var ctx = DatabaseContext.GetOpenConnection())
{
using (var cmd = ctx.CreateCommand("select 2"))
{
cmd.ExecuteNonQuery();
}
}
// leaves connection open
}

For automated testing purposes, it's usually easier to pass it in. This is called dependency injection.
When you need to write tests, you can create a mock database connection object and pass that instead of the real one. That way, your automated tests won't rely on an actual database that needs to be repopulated with data every time.

I personally work to centralize my data access as much as possible, however, if not possible I ALWAYS open a new connection in the other classes, as I find that there are too many other things that can get in the way when passing the actual connection object.

Here is a little more insight into this problem. I have a class that manages db connections, and have 2 classes that implement an interface. One of the classes is for SQL and the other is of OLAP. The manager is the one that knows which connection to use, so it could pass the exact connection to the type, or the type can create his own connection.

You can pass connection objects without any problem (for instance Microsoft Enterprise Library allows static method calls passing in a connection) or you could manage it externally its up to your design, there are not direct technical tradeoffs.
Be careful for portability not to pass an specific connection if your solution will be ported to other databases (meaning don´t pass a SqlConnection it you plan to work with other databases)

Setting up the connection is potentially expensive and potentially adds a round trip. So, again, potentially, the better design is to pass the connection object.
I say potentially, because if you are a Microsoft ADO app, you are probably using a connection pool....

I would suggest that you distinguish between the connection object and its state (open, closed).
You can have a single method (or property) that reads the connection string from web.config. Using the same version of the connection string every time ensures that you will benefit from connection pooling.
Call that method when you need to open a connection. At the very last moment, after setting up all of the SqlCommand properties, open the connection, use it, and then close it. In C#, you can use the using statement to make sure the connection is closed. If not, be sure to close the connection in a finally block.

I would use the web.config
<configuration>
<connectionStrings>
<add name="conn1" providerName="System.Data.SqlClient" connectionString="string here" />
<add name="conn2" providerName="System.Data.SqlClient" connectionString="string here" />
</connectionStrings>
</configuration>
Then you can reference it from anywhere in the application

Related

Sharing a connection and a transaction in EF across multiple contexts (UnintentionalCodeFirstException)

The previous version and question are provided as an added context below. The improved problem formulation and question could be as follows:
How does one share a transaction between multiple contexts in EF 6.1.0 database first and .NET 4.5.2 without doing a distributed transaction?
For that it looks like I need to share a connection between the multiple contexts, but the code examples and tutorials I've been looking at thus far haven't been that fruitful. The problem looks like is hovering around on how to define a functioning combination of a connection object and transaction object types so that EF database first object metadata is also built and found when constructing the object contexts.
That is, I would like to do akin to what has been described in the EF 6.n tutorials here. Some example code could be
int count1;
int count2;
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
//How to define this connection so as not to run into UnintentionalCodeFirstException?
//Creating a dummy context to obtain the connectiong string like so
//dummyContext.Database.Connection.ConnectionString and then using the connection will be greeted with the aforementioned exception.
using(var conn = new SqlConnection("..."))
{
using(var c1 = new SomeEntities(conn, contextOwnsConnection: false))
{
//Use some stored procedures etc.
count1 = await c1.SomeEntity1.CountAsync();
}
using(var c2 = new SomeEntities(conn, contextOwnsConnection: false))
{
//Use some stored procedures etc.
count2 = await c2.SomeEntity21.CountAsync();
}
}
}
int count = count1 + count2;
In the examples there are also other methods as to how to create a shared connection and a transaction, but as written, the culprit seem to be that if, say, I provide the connectiong string in (the "..." part) the previous snippet as dummyContext.Database.Connection.ConnectionString I'll get just an exception.
I'm not sure if I'm just reading the wrong sources or if there's something else that's wrong in my code when I try to share a transaction across multiple EF contexts. How could it be done?
I've read quite a few other SO posts regarding this (e.g. this) and some tutorials. They did not help.
I have a strange problem in that it looks I don't have the constructor overloads defined as in other tutorials and posts. That is, taking the linked tutorial link, I can't write new BloggingContext(conn, contextOwnsConnection: false)) and use a shared connection and an external transaction.
Then if I write
public partial class SomeEntities: DbContext
{
public SomeEntities(DbConnection existingConnection, bool contextOwnsConnection): base(existingConnection, contextOwnsConnection) { }
}
and use it like in the tutorials, I get an exception from the following line from the following T4 template generated code
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
I'm using .NET 4.5.2 and EF 6.1.0. I'ved constructed the edmx from an existing database and generated the code from there. In this particular situation I'm using Task Parallel threads to load dozens of SQL Server Master Data Services staging tables (yes, a big model) and to call the associated procedures (provided by the MDS one per table). MDS has its own compensation logic in case staging to some of the tables fails, but rolling back a transaction should be doable too. It just looks like I have a (strange) problem with my EF.
<Addendum: Steve suggested using straight TransactionScope. Without a shared connection that would require a distributed transaction, which isn't an option I can choose. Then if I try to provide a shared connection for the contexts (some options shown in the tutorials, one here I have the problem of "missing constructors". When I define one, I get the exception I refer in the code. All in all, this feels quite strange. Maybe there's something wrong in how I go about generating the DbContext and related classes.
<Note 1: It looks like the root cause is as in this blog post by Arthur (of EF developer team) Don't use Code First by mistake. That is, in database first development the framework seeks for the class-relational mappings as defined in the connection string. Something fishy in my connection string that is..?
Have you tried wrapping the calls in a transaction scope?
using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
{
// Do context work here
context1.Derp();
context2.Derp();
// complete the transaction
scope.Complete();
}
Because of connection pool, using multiple EF DbContext which are using exactly the same connection string, under same transaction scope will usually not result in DTC escalation (unless you disabled pooling in connection string), because the same connection will be reused for them both (from the pool). Anyway, you can reuse the same connection in your case like this (I assume you already added constructor which accepts DbConnection and flag indicating if context owns connection):
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) {
// important - use EF connection string here,
// one that starts with "metadata=res://*/..."
var efConnectionString = ConfigurationManager.ConnectionStrings["SomeEntities"].ConnectionString;
// note EntityConnection, not SqlConnection
using (var conn = new EntityConnection(efConnectionString)) {
// important to prevent escalation
await conn.OpenAsync();
using (var c1 = new SomeEntities(conn, contextOwnsConnection: false)) {
//Use some stored procedures etc.
count1 = await c1.SomeEntity1.CountAsync();
}
using (var c2 = new SomeEntities(conn, contextOwnsConnection: false)) {
//Use some stored procedures etc.
count2 = await c2.SomeEntity21.CountAsync();
}
}
scope.Complete();
}
This works and does not throw UnintentionalCodeFirstExce‌​ption because you pass EntityConnection. This connection has information about EDMX metadata and that is what database first needs. When you pass plain SqlConnection - EF has no idea where to look for metadata and actually doesn't even know it should look for it - so it immediately assumes you are doing code-first.
Note that I pass EF connection string in code above. If you have some plain SqlConnection which you obtained by some other means, outside EF, this will not work, because connection string is needed. But, it's still possible because EntityConnection has constructor which accepts plain DbConnection. However, then you should pass reference to metadata yourself. If you are interested in this - I can provide code example of how to do that.
To check that you indeed prevent escalation in all cases - disable pooling (Pooling=false in connection string) and stop DTC service, then run this code - it should run fine. Then run another code which does not share the same connection and you should observe error indicating escalation was about to happen but service is not available.

does declaring a variable in namespace makes it global

i am writing a windows form based application that uses database and
i want to declare the following as global so that i can just use vcon.open()
and vcon.close() to open and close my database from which ever form i want. please tell how to do it.
OleDbConnection vcon = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=F:\workspace\RDASMS\RDASMS\rdadb.mdb");
Connections are quite lightweight, so you can just create and close them as needed. Maybe like this:
using (var conn = new OleDbConnection(connStr))
{
// Use your connection
}
This will automatically close the connection for you when the block exits.
You might like to put the string in a globally accessible place, such as a Config class.
As the others have stated, "global" static types are not usually the best design approach, but to answer your specific question:
namespace YourApplicationNamespace
{
public static class MyOleDbConnection
{
public static OleDbConnection OleDbConnection;
public static void Open()
{
// Do Something with OleDbConnection.
}
public static void Close()
{
// Do Something with OleDbConnection.
}
}
}
Can be used as:
MyOleDbConnection.Open();
MyOleDbConnection.Close();
First of all you can't declare something global in a namespace. And even if it was possible it is not a nice idea. Appreciating your effort in avoiding code duplication, I suggest you to:
Place the connection string in the configuration.
Declare the connection and use it when needed, maybe with an using pattern.
a point about 2: I noticed you use a jet engine ( Access ) this can result in a performance drawback by opening and closing the connection on demand, or at least was as this in the past. In any case note than opening the connection when needed and close it as soon you have done is the pattern to follow in any other case.
You can create a static class with static members.
public static MyConnection
{
public static OleDbConnection Connection = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\workspace\RDASMS\RDASMS\rdadb.mdb");
}
Then you can access it like:
var vcon = MyConnection.Connection;
vcon.Open();
Doing it this way adds a unnecessary layer of complexity to your program. You should either create a class that strictly handles database access such as the MyConnection example above. You would need to add the appropriate methods to actually handle the access. Using the Jet provider can introduce significant performance implications when opening and closing a file constantly. You should only close it if there will be long periods of inactivity on the connection. In that case you should do something more along the lines of:
using(var vcon = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\workspace\RDASMS\RDASMS\rdadb.mdb"))
{
// Your code here...
}
This will close the connection once your operations are complete. But don't forget about the performance issues that can arise from this.

Disposing of SQL Connection

I have a SQL class that connects to the DB and retreives a DataTable. I am aware that the SqlConnection must be disposed when finished. I know this can be done using a using block, but is it also acceptable to put the Dispose() call inside the destructor of this class?
Herre is my code:
public class SQLEng
{
//Connection String Property
//Must be set to establish a connection to the database
public string ConnectionString{ get; set; }
SqlConnection _Conn;
//Overridden Constructor enforcing the Connection string to be set when created
public SQLEng(string connectionString)
{
ConnectionString = connectionString;
_Conn = new SqlConnection(connectionString);
}
//ensure the SqlConnection is disposed when destructing this object
public ~SQLEng()
{
_Conn.Dispose();
}
//various other methods to get datatables etc...
}
Basically i wish to have a class variable SqlConnection, rather than instantiate the SqlConnection inside every method that accesses the DB. Is this sound practise?
Your design encourages hanging on to a (presumably open) SqlConnection for long periods of time. Best practice is to open a connection just before you need it and then release (close and dispose) it as soon as you are finished.
Yes, there is some overhead associated with creating new connections; connection pooling alleviates much of that processing time. Worse is keeping many connections alive on the server.
Looking at the source for the Enterprise Library (from the MS Patterns & Practices team), the DAAB creates a connection as needed and disposes it as quickly as possible.
public virtual int ExecuteNonQuery(DbCommand command)
{
using (var wrapper = GetOpenConnection())
{
PrepareCommand(command, wrapper.Connection);
return DoExecuteNonQuery(command);
}
}
protected DatabaseConnectionWrapper GetOpenConnection()
{
DatabaseConnectionWrapper connection = TransactionScopeConnections.GetConnection(this);
return connection ?? GetWrappedConnection();
}
So I would say that is a best practice. In most cases, all you are doing is returning the connection to the connection pool, so really the connection is not closed per se.
If you wish to wrap the SQL Connection class, implement IDisposable and call the connection Dispose() from within your own Dispose() method. More info is here:
Properly disposing of a DbConnection
As to whether or not this is good practice - well, if all your doing is wrapped the SQL connection in another class, I'm not sure what you're achieving. All your methods will still need access to the instance of this class, in which case they could get access to the instance of the connection object by itself.

Is it best to pass an open SqlConnection as a parameter, or call a new one in each method?

If methods/functions I'm going to call involve the need of an open SqlConnection, I will open this up in the method which is calling the function. For example:
protected static void btnSubmit(){
conn.Open();
myMethod(someParam, conn);
conn.Close();
}
protected static void myMethod(object someParam, SqlConnection conn){
//Some SQL commands etc here..
}
I do this so that I:
Only ever open and close 1 SqlConnection per process
However, would it be better to structure my code like so:
protected static void btnSubmit(){
myMethod(someParam);
}
protected static void myMethod(object someParam){
SqlConnection conn = New SqlConnection(".....");
conn.Open();
//Some SQL commands etc here..
conn.Close();
}
The advantage I see of structuring it this way is:
I don't have to pass an extra parameter for each method
If later down the line the method no longer has a SQL command, there is not an unused parameter being called each time
The disadvantage I see to this, is:
If myMethod is a recursive method, then when it calls itself its going to be opening another SqlConnection, and so on, and so on..
If btnSubmit is calling multiple methods which all require a SqlConnection, each one is going to open and close a new connection.
What is the best way of doing this, and which is most commonly practised?
ADO.NET uses connection pooling, so it automatically reuses existing opened connections, even when you think that you are opening a new connection. Having that in mind, there is really no reason to pass a connection through your code (as a parameter). This will make your code much cleaner, with the same performance as when you were passing the connection as a parameter.
More details here
Also (and this is really important), please, use the "using" keyword. That way, you will not have to deal with closing the connection and cleanup, because your code as it is written now doesn't deal with closing the connections, so in a case of some exception you might end up with hitting connection limit on your server. Go with something like this:
using(var connection = new SqlConnection(<connection_string>))
{
connection.Open();
using(var command = connection.CreateCommand())
{
}
}
As you can see, there is no need to call connection.Close() or deal with exceptions and closing the connection in your finally block, because that is a "job" for the "using" block.
Also, one important note...transactions are not passed via connection polling, so if you want to keep your transaction across method calls, you will have to pass your connection (and that is the only reason I can think of why you should do that).
The best pattern to use is Repository+UnitOfWork patterns.
So repository is created and passed the UnitOfWork which contains the connection. After work is done UnitOfWork is disposed.
// Pseudocode
using(UnitOfWork uow = new UnitOfWork())
{
Repository.Init(uow);
Repository.SaveInDb(stuff);
}
And Unit of work:
// PseudoCode
class UnitOfWork : IDisposable
{
public UnitOfWork()
{
conn = new SqlConnection();
conn.Open();
}
public void Dispose()
{
conn.Close();
}
....
}
This is what I always use.
Some people prefer simpler approach where Repository owns connection. This is simpler but in case you need to have a transaction across multiple repositories, it will not work.

work with an already open database connection

This is a little wierd, but I want to check if connection to my database is already open or not? How do I check that? and if open I want to be able to work with it straightaway without going through all the statements:
sqlconnection conn = new sqlconnection("string ...");
Can this be done? I know the connection string and the connection name too. I want to check if this connection is available first and then proceed.
If you know the connection string then the easiest way of obtaining a new usable sql connection is to create a new instance of the SqlConnection class:
using (SqlConnection conn = new SqlConnection("MyConnectionString"))
{
conn.Open();
// Use the connection
}
The .Net framework uses connection pooling and so there is no need to worry about opening efficiency & multiple connections - the above code will either re-use an available existing connection, or create a new one as required.
If you want to save yourself some typing then you might find it useful to create yourself a small helper method or property:
class SqlHelper
{
public static SqlConnection GetConn()
{
SqlConnection returnValue = new SqlConnection("MyConnectionString");
returnValue.Open();
return returnValue;
}
}
Usage:
using (SqlConnection conn = SqlHelper.GetConn())
{
// Use the connection
}
Have you looked at the documentation for SqlConnection?
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.aspx
I believe the "State" property will tell you what you want.
If you are rather asking more generally how you can use an existing connection from a connection pool, this will be done automatically when you create a new SqlConnection with an identical connection string as an active connection.
If you're just trying to avoid writing redundant code, then put it in a class and reuse it.
Although you are probably just using SQL Server it might be good practice to get familiar with all the core interfaces in System.Data since all data providers implement them. I believe the State property on IDbConnection returns the information you are asking for (IDbConnection)
Also you may want to hide that logic in some kind of centralized method:
public static IDbConnection RetrieveConnection(){
if(DataAccess.Connection.State == ConnectionState.Open) return DataAccess.Connection;
conn.Dispose(); //to be clean, I believe this is safe if it's already disposed
//retrieve configured connection string
//create and open connection
return DataAccess.Connection;
}
So maybe DataAccess is some place you can put and retrieve your connection object, but I would avoid having everyone use it directly. Instead have them go through this method that can ensure the connection is usable. I'm just trying to give you ideas.
Also you may want to take it a step further and use something like NHibernate that will manage connections and all that stuff for you. Although that's not always worth the effort if the project is small.
EDIT: made the code a little more explicit
The Façade Design Pattern should help you here. Here's an example.
Façade Pattern (wikipedia);
Façade Design Pattern (Gang of Four).
An "intelligent" façade knows what method needs to connect where, etc. The façade opens the connection and pass it to an underlying piece of code, generally contained in a factory class or something alike.
public class DoSomethingFacade {
private static readonly DoSomethingFactory _doSomethingFactory = new DoSomethingFactory();
public static IList<T> GetList<T>() {
using(IDbConnection connection = OpenConnection("string..."))
return _doSomethingFactory.GetList<T>(connection);
}
public static IDbConnection OpenConnection(string connectionString) {
IDbConnection openedConnection = new SqlConnection(connectionString);
openedConnection.Open();
return openedConnection;
}
}
internal class DoSomethingFactory {
internal DoSomethingFactory() { }
internal IList<T> GetList<T>(IDbConnection connection) {
IList<T> results = new List<T>();
// use connection here without caring about it,
// as it should be provided as an opened available connection.
return results;
}
}

Categories

Resources