For the below method I want to pass in a mock of the DbProviderFactories class but can't because it's a static class:
private DbConnection GetConnection()
{
var dbProviderFactory = DbProviderFactories.GetFactory(_name);
try
{
var dbConnection = dbProviderFactory.CreateConnection();
if (dbConnection == null) return null;
dbConnection.ConnectionString = _connectionString;
return dbConnection;
}
catch (Exception)
{
return null;
}
}
How can I test my code / how can I mock DbProviderFactories?
You could create your own non-static wrapper for DbProviderFactory that implements your own interface and calls the static method:
public interface IDbProviderFactories
{
DbProviderFactory GetFactory(string name);
}
public class MyDbProviderFactories : IDbProviderFactories
{
public DbProviderFactory GetFactory(string name)
{
return DbProviderFactories.GetFactory(name);
}
}
If you now inject this into your class that exposes GetConnection() you can mock an implementation of the interface as needed.
Related
I am using Visual Studio 2010, .NET Framework 4.
I am getting type used in a using statement must be implicitly convertible to 'System.IDisposable' error although I am implementing IDisposable so I am not sure where I am making the mistake. Please check and let me know.
I have a class named MyDatabaseContext which contains DbConnection; it implements IDisposable :
public abstract class MyDatabaseContext : IDisposable
{
private string _dataProvider;
private string _connectionString;
private DbConnection _dbConnection;
public MyDatabaseContext(string dataProvider, string connectionString)
{
_dataProvider = dataProvider;
_connectionString = connectionString;
}
public void OpenConnection()
{
DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory(_dataProvider);
_dbConnection = dbProviderFactory.CreateConnection();
_dbConnection.ConnectionString = _connectionString;
_dbConnection.Open();
}
public void Dispose()
{
if (_dbConnection != null)
{
if (_dbConnection.State != ConnectionState.Closed)
{
_dbConnection.Close();
}
_dbConnection.Dispose();
_dbConnection = null;
}
}
}
Now I have a class EmployeeDatabaseContext which inherit from MyDatabaseContext. In it I have a method test() where I am calling the parent class's OpenConnection() method inside using block.
public class EmployeeDatabaseContext : MyDatabaseContext
{
public EmployeeDatabaseContext(string dataProvider, string connectionString)
: base(dataProvider, connectionString)
{
}
public void test()
{
using (OpenConnection())
{
}
}
}
Problem is I am getting error when I build. Error is in EmployeeDatabaseContext class in test() method on the using block. The error is
'void': type used in a using statement must be implicitly convertible
to 'System.IDisposable'
But the parent class MyDatabaseContext is implementing IDisposable so I dont know why I am getting this error.
Thanks
OpenConnection() returns void. To use it in a using statement, it needs to return an object that implements IDisposable. It doesn't matter what the class owing the method implements. The using statement doesn't go off looking for something nearby to dispose. It disposes exactly what you give it, and you're not giving it anything.
So:
public MyDatabaseContext(string dataProvider, string connectionString)
{
_dataProvider = dataProvider;
_connectionString = connectionString;
OpenConnection();
}
But let OpenConnection() not be public, as you don't want interlopers calling it redundantly:
protected void OpenConnection()
{
// ...
}
You're correctly calling the base constructor in EmployeeDatabaseContext's constructor, so that's fine.
And here's how you use it in a using statement:
public void test()
{
using (var ctxt = new EmployeeDatabaseContext(someProviderString, someConnString))
{
// Do stuff with ctxt
// ctxt.Dispose() will be called when control exits this block.
}
}
I have a unitofWork class and a repository that uses it
something along the lines of this:
unit of work
private SqlConnection _conn;
private TransactionScope _ts;
public UnitOfWork(SqlConnection conn, TransactionScope ts)
{
_ts = ts;
_conn = conn;
_conn.EnlistTransaction(Transaction.Current);
}
public SqlConnection Connection
{
get { return _conn; }
}
public void Save()
{
_ts.Complete();
}
#region IDisposable
public void Dispose()
{
if (_conn != null)
{
_conn.Dispose();
_conn = null;
}
if (_ts != null)
{
_ts.Dispose();
_conn = null;
}
}
repository
SqlConnection _conn;
public Repository(IUnitOfWork uow)
{
_conn = uow.Connection;
}
// some methods
public void Dispose()
{
if (_conn != null)
{
_conn.Dispose();
_conn = null;
}
}
I am using it like this
using (var uow = new UnitOfWork())
{
using (var repo = new Repository(uow))
{
if (repo.UpdateStuff())
{
uow.Save();
}
}
}
the dispose method is first called in the repo, which disposes and nulls the connection. but then when it we get to the uow dispose, the connection is no longer null and is disposed 'again'
I am sure I am being dull, but can anyone explain please
thanks
The right part of the statement
_conn = uow.Connection;
actually returns a copy of the object reference, not the reference itself.
So what you're setting to null in the Repository Dispose method is the local reference to the connection, which is different from the connection reference in the UnitOfWork instance.
If you really want to keep this behavior ( having the UnitOfWork Connection property set to null by the Repository Code), you must set the uow.Connection to null, not the local reference _conn.
I tried to close a connection in the destructor of my class, to be sure that if I forget to close it - it close automatically, and it fires an exception.
I searched a little and I founded here that It can't be done.
Now I tried to close it twice - and it works!!!
But I'm wondering if it's a good solution.
what do you think?
here is the code
public class MyCommand : IDisposable
{
public readonly DbCommand command;
public MyCommand(string ConnectionString, DbProviderFactory factory)
{
var tempConnexion = factory.CreateConnection();
tempConnexion.ConnectionString = ConnectionString;
tempConnexion.Open();
var t = tempConnexion.BeginTransaction(IsolationLevel.ReadCommitted);
command = tempConnexion.CreateCommand();
command.Connection = tempConnexion;
command.Transaction = t;
}
public MyCommand(string ConnectionString, DbProviderFactory factory, string requete)
: this(ConnectionString, factory)
{
command.CommandText = requete;
}
public MyCommand(string ConnectionString, string provider)
: this(ConnectionString, DbProviderFactories.GetFactory(provider)) { }
public MyCommand(string ConnectionString, string provider, string requete)
: this(ConnectionString, DbProviderFactories.GetFactory(provider), requete) { }
public static implicit operator DbCommand(myCommand c)
{
return c.command;
}
public void Dispose()
{
try
{
var t = command.Transaction;
if (t != null)
{
t.Commit();
t.Dispose();
}
}
catch { }
try
{
if (command.Connection != null)
command.Connection.Dispose();
command.Dispose();
}
catch { }
}
~MyCommand()
{
if (command != null && command.Connection != null && command.Connection.State == ConnectionState.Open)
for (int i = 0; i < 2; i++)//twice to get the handle - it's working!
Dispose();
}
}
The connection is closed by the Dispose method not by the Destructor.
Also see the MSDN caution
Caution
Do not call Close or Dispose on a Connection, a DataReader, or any
other managed object in the Finalize method of your class. In a
finalizer, you should only release unmanaged resources that your class
owns directly. If your class does not own any unmanaged resources, do
not include a Finalize method in your class definition.
A much better and recommended way to deal with connection is to use USING statement which is equivalent to saying like
try
{
// your code
}
finally
{
myobject.Dispose();
}
I have a console application with a base class as following:
public abstract class PaymentSystemBase : IPayable
{
private SqlConnection _connection;
protected PaymentSystemBase()
{
CreateDatabaseConnection();
}
protected void CreateDatabaseConnection()
{
if(_connection == null)
{
string connectionString = ConfigurationManager.AppSettings["connString"];
var connection = new SqlConnection(connectionString);
_connection = connection;
connection.Open();
}
}
public SqlConnection Connection
{
get { return _connection; }
}
public abstract void ProcessPayment();
}
And have a few classes that derive from PaymentSystemBase:
public class PS1 : PaymentSystemBase
{
public override void ProcessPayment()
{
// Work with database using Connection from PaymentSystemBase
}
}
public class PS2 : PaymentSystemBase
{
public override void ProcessPayment()
{
// Work with database using Connection from PaymentSystemBase
}
}
In main program:
var lstPayments = new List<IPayable>
{
new PS1(),
new PS2()
};
var processPayments = new ProcessPayments(lstPayments);
processPayments.Process();
Where:
public class ProcessPayments
{
private List<IPayable> _paymentSystems;
public ProcessPayments(List<IPayable> paymentSystem)
{
_paymentSystems = paymentSystem;
}
public void Process()
{
foreach (var paymentSystem in _paymentSystems)
{
paymentSystem.ProcessPayment();
}
}
}
My question is how to use the same connection from PaymentSystemBase class and close it after processing? As I can see the connection was created again every time when PS1 and PS2 were created.
You shouldn't try to share the connection object. The connection objects themselves are actually quite lightweight, being an abstraction built on top of the actual physical connections, that the ADO.NET connection pool takes care of creating.
So you base class should be something like:
public abstract class PaymentSystemBase : IPayable
{
private static string _connectionString =
ConfigurationManager.ConnectionStrings["connString"].ConnectionString
public static string ConnectionString
{
get { return _connection; }
}
public abstract void ProcessPayment();
}
And then your derived classes should be:
public class PS1 : PaymentSystemBase
{
public override void ProcessPayment()
{
using(var conn = new SqlConnection(PaymentSystemBase.ConnectionString))
{
using(var cmd = new SqlCommand("...",conn)
{
//Prepare command
conn.Open();
cmd.ExecuteXXX();
//Process results, etc
}
}
}
}
You'll notice that I've also switched where the connection string is loaded from via the ConfigurationManager class from AppSettings to ConnectionStrings, which is a dedicated part of the configuration system for storing connection strings. This wasn't actually required but it is more conventional.
My class has the following core:
class SmartDbConnection
{
private readonly IDbConnection Connection;
public SmartDbConnection(string ConnectionString)
{
if(ConnectionString.Contains("MultipleActiveResultSets=true"))
{
Connection = new SqlConnection(ConnectionString);
}
}
}
I don't want it to have "SqlConnection" hardcoded. So I thought in making it a Generic class (accepting IDbConnection classes). But I don't know how to do it. Anyone can help?
First - I've added IDisposable to this, as I believe it is important.
Second, note that providers are an alternative here:
class SmartDbConnection
{
private DbConnection Connection;
public SmartDbConnection(string provider, string connectionString)
{
Connection = DbProviderFactories.GetFactory(provider)
.CreateConnection();
Connection.ConnectionString = connectionString;
}
public void Dispose() {
if (Connection != null)
{
Connection.Dispose();
Connection = null;
}
}
}
If you must go generic, how about:
class SmartDbConnection<T> : IDisposable where T : class,
IDbConnection, new()
{
private T Connection;
public SmartDbConnection(string connectionString)
{
T t = new T();
t.ConnectionString = connectionString;
// etc
}
public void Dispose() {
if (Connection != null)
{
Connection.Dispose();
Connection = null;
}
}
}
Why don't you accept IDbConnection instead of connectionstring to your ctor?
Maybe...
class SmartDbConnection<T> where T : IDbConnection, new()
{
private readonly IDbConnection Connection;
public SmartDbConnection(string connectionString)
{
if (connectionString.Contains("MultipleActiveResultSets=true"))
{
Connection = new T();
Connection.ConnectionString = connectionString;
}
}
}
EDIT: But what kaanbardak suggests can be even better...
If you don't want to specify SqlConnection there, where would you specify it - and how would you know to use it only if the connection string contains "MultipleActiveResultSets=true"?
I suspect at some level you want a connection factory - either a Func<string, IDbConnection> you can pass in or set somewhere, or possibly just a class:
public static class ConnectionFactory
{
public static IDbConnection CreateConnection(string connectionString)
{
// Hard-code stuff here
}
}
Of course, they're just two sides of the same coin - ConnectionFactory is just a static implementation of the Func<string, IDbConnection>.
class SmartDbConnection<T> where T: IDbConnection , new()
{
private readonly T Connection;
public SmartDbConnection(string ConnectionString)
{
if (ConnectionString.Contains("MultipleActiveResultSets=true"))
{
Connection = new T();
Connection.ConnectionString = ConnectionString;
}
}
}