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.
Related
I am currently following this instructions on how to do a query with raw sql on ef.
https://learn.microsoft.com/en-us/ef/ef6/querying/raw-sql
Is it possible to do a raw sql read query(ies) on a database context in such a way so we are sure, that we use only one database connection during request processing.
Similar to this, but with DBContext instead od IDBConnection.
public class SqlConnectionFactory : ISqlConnectionFactory, IDisposable
{
private readonly string _connectionString;
private IDbConnection _connection;
public SqlConnectionFactory(string connectionString)
{
this._connectionString = connectionString;
}
public IDbConnection GetOpenConnection()
{
if (this._connection == null || this._connection.State != ConnectionState.Open)
{
this._connection = new SqlConnection(_connectionString);
this._connection.Open();
}
return this._connection;
}
public void Dispose()
{
if (this._connection != null && this._connection.State == ConnectionState.Open)
{
this._connection.Dispose();
}
}
}
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 am trying to initialize a static variable from a static method but after it has been initialized it is still null. What am I doing wrong?
class Database {
public static Database Connection = null;
public static void Create() {
Database.Connection = new Database();
if (Database.Connection == null) {
Console.WriteLine("Null");
}
}
public Database() {
Console.WriteLine("I got called");
}
}
Am I missing something here? Database.Connection is NULL after calling the method although the constructor has been called.
class Database {
public static Database Connection = null;
static Database() {
Database.Connection = new Database();
if (Database.Connection == null) {
Console.WriteLine("Null");
}
}
public Database() {
Console.WriteLine("I got called");
}
}
You never call the Create(). You can use static constructor for this, if you'd like, as I've done above.
Use Static constructor, to initialize static field.
static Database()
{
Database.Connection = new Database();
}
One option is to make the static member a Property:
class Database
{
private static Database _connection = null;
public static Database Connection
{
get
{
if(null == _connection)
{
_connection = new Database();
}
return _connection;
}
}
}
If you are implementing a singleton, then you should hide the constructor by making it private.
private Database()
{
// This will only be called once, when the Connection
// property getter is first accessed and the private
// _connection field is still null. Note: when using
// the debugger, this may be before it is actually called
// explicitly from within your code!
Console.WriteLine("Database() constructor called");
}
Firstly, am new to C# programming.
I have created a dedicated class to get the connection string from the app.config of a Web Services application in Visual Studio 2010 as per the code below.
On building the code I get the following error via the catch block:
"The name 'connection' does not exist in the current context".
Obviously connection is going out of scope.
How do I avoid this error?
Is the Dispose method being used correctly here?
public class FCSConnection : IDisposable
{
public string GetDefaultConnectionString()
{
string DefaultConnectionString = null;
try
{
DefaultConnectionString = ConfigurationManager.AppSettings["ConnectionString"];
SqlConnection connection = new SqlConnection(DefaultConnectionString);
connection.Open();
return DefaultConnectionString;
}
catch (Exception)
{
if (DefaultConnectionString != null)
{
connection.Dispose();
}
}
return DefaultConnectionString;
}
public void Dispose()
{
throw new NotImplementedException();
}
}
The exact compiler message refers to your catch statement:
connection.Dispose();
Here, connection is an unknown name, because it's declared inside the try block.
As for your entire code, I think it's also wrong. If you want your FCSConnection class to encapsulate the SQL connection, you should declare connection as a private member and then dispose it in your Dispose() method.
public class FCSConnection : IDisposable
{
private SqlConnection connection = null;
public string GetDefaultConnectionString()
{
string defaultConnectionString = null;
try
{
defaultConnectionString = ConfigurationManager.AppSettings["ConnectionString"];
connection = new SqlConnection(defaultConnectionString);
connection.Open(); // are you sure want to keep the connection being opened??
}
catch
{
Dispose();
}
return defaultConnectionString;
}
public void Dispose()
{
if (connection != null)
{
connection.Dispose();
connection = null; // to avoid repeat dispose
}
}
}
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;
}
}
}