This is the code we are using to insert records in Oracle database
using (Oracle.DataAccess.Client.OracleConnection conn =
new Oracle.DataAccess.Client.OracleConnection(ConnectionString))
{
conn.Open();
using (Oracle.DataAccess.Client.OracleBulkCopy c = new
Oracle.DataAccess.Client.OracleBulkCopy(conn, UseInternalTransaction)
)
{
c.DestinationTableName = string.Format("{0}.{1}", Schema, Destination);
c.WriteToServer(dtLimitStatsDetails);
c.Close();
}
}
After some time of running this code we started receiving below error
ORA-01012: not logged on
On inspection we found that there are ~20,000 sessions with this ConnectionString i.e. sessions (connections) are not being closed.
The connection is automatically closed at the end of the using
block
It looks 'using' is not closing Connections, Why?
using statement, provides a convenient syntax that ensures the correct use of IDisposable objects.
https://msdn.microsoft.com/en-us/library/yh598w02.aspx
SqlConnection class has an overriden method which is closing the connection.
protected override void Dispose(bool disposing)
{
if (disposing)
{
this._userConnectionOptions = (DbConnectionOptions) null;
this._poolGroup = (DbConnectionPoolGroup) null;
this.Close();
}
this.DisposeMe(disposing);
base.Dispose(disposing);
}
if you're using a custom OracleConnection class, you must implement IDisposable interface and close connection in Dispose method.
if not, close connection manually and check if there is an error.
last advice, unwrap OracleConnection using statement;
using (Oracle.DataAccess.Client.OracleBulkCopy c = new Oracle.DataAccess.Client.OracleBulkCopy(ConnectionString, UseInternalTransaction))
{
c.DestinationTableName = string.Format("{0}.{1}", Schema, Destination);
c.WriteToServer(dtLimitStatsDetails);
c.Close();
}
Related
I tried this code on an array of 3 connection strings without any complaints.My question is, is it okay to invoke multiple dispose calls on the same object?
foreach (var s in strings)
{
connection.ConnectionString = s;
connection.Open();
connection.Close();
connection.Dispose();
}
Here is one way to do it:
bool TestConnection<T>(string connectionString) where T : IDbConnection, new
{
using(T con = new T())
{
con.ConnectionString = connectionString;
connection.Open();
return true;
}
}
Another way to implement connection testing code is with an extension method (note this does not dispose the connection object):
public static Tuple<bool, Exception> TestConnection(this IDbConnection connection)
{
try
{
connection.Open();
connection.Close();
return new Tuple<bool, Exception>(true, null);
}
catch(Exception e)
{
return new Tuple<bool, Exception>(false, e);
}
}
Please note in this version I'm returning a Tuple of bool and Exception so whoever use this code can get the information on why the connection failed, but not have to wrap the call in a try...catch block. Of course, you can choose to simply return a bool just like in the first example, this is just for demonstration purposes.
You should fix your code this way:
foreach (var s in strings)
{
connection.ConnectionString = s;
connection.Open();
connection.Close();
}
Connection doesn't need to dispose, or atleast you shoudln't dispose an object that you want to use again.
Anyway this isn't a good approach.
You should have a
using(DbContext db = new DbContext()){
//SQL Actions
}
for every db relative code, to avoid problems ^^
public bool TestConnection(IDbConnection con)
{
using (con)
{
try
{
con.Open();
con.Close();
return true;
}
catch
{
return false;
}
}
}
It's "ok" with what you are doing (completely different connect everytime with no ran queries) but as Amy said in the comments, it really doesn't get you anything special. Should probably abide by the wisdom of not reusing disposed objects.
Also for SqlConnection, calling Close then dispose is repetitive since it will call its close upon dispose.
Going to throw my code into the mix as well, comments in code:
private bool DBValidCheck(string connection)
{
//Using statement releases the object that implement iDisposable once it exits the block. Takes care of the dispose
using (var connection = new SqlConnection(connection))
{
try
{
connection.Open();
return true;
}
catch
{
return false;
}
}
}
Which is the proper way of using BeginTransaction() with IDbConnection in Dapper ?
I have created a method in which i have to use BeginTransaction(). Here is the code.
using (IDbConnection cn = DBConnection)
{
var oTransaction = cn.BeginTransaction();
try
{
// SAVE BASIC CONSULT DETAIL
var oPara = new DynamicParameters();
oPara.Add("#PatientID", iPatientID, dbType: DbType.Int32);
..........blah......blah............
}
catch (Exception ex)
{
oTransaction.Rollback();
return new SaveResponse { Success = false, ResponseString = ex.Message };
}
}
When i executed above method - i got an exception -
Invalid operation. The connection is closed.
This is because you can't begin a transaction before the connection is opened. So when i add this line: cn.Open();, the error gets resolved. But i have read somewhere that manually opening the connection is bad practice!! Dapper opens a connection only when it needs to.
In Entity framework you can handle a transaction using a TransactionScope.
So my question is what is a good practice to handle transaction without adding the line cn.Open()... in Dapper ? I guess there should be some proper way for this.
Manually opening a connection is not "bad practice"; dapper works with open or closed connections as a convenience, nothing more. A common gotcha is people having connections that are left open, unused, for too long without ever releasing them to the pool - however, this isn't a problem in most cases, and you can certainly do:
using(var cn = CreateConnection()) {
cn.Open();
using(var tran = cn.BeginTransaction()) {
try {
// multiple operations involving cn and tran here
tran.Commit();
} catch {
tran.Rollback();
throw;
}
}
}
Note that dapper has an optional parameter to pass in the transaction, for example:
cn.Execute(sql, args, transaction: tran);
I am actually tempted to make extension methods on IDbTransaction that work similarly, since a transaction always exposes .Connection; this would allow:
tran.Execute(sql, args);
But this does not exist today.
TransactionScope is another option, but has different semantics: this could involve the LTM or DTC, depending on ... well, luck, mainly. It is also tempting to create a wrapper around IDbTransaction that doesn't need the try/catch - more like how TransactionScope works; something like (this also does not exist):
using(var cn = CreateConnection())
using(var tran = cn.SimpleTransaction())
{
tran.Execute(...);
tran.Execute(...);
tran.Complete();
}
You should not call
cn.Close();
because the using block will try to close too.
For the transaction part, yes you can use TransactionScope as well, since it is not an Entity Framework related technique.
Have a look at this SO answer: https://stackoverflow.com/a/6874617/566608
It explain how to enlist your connection in the transaction scope.
The important aspect is: connection are automatically enlisted in the transaction IIF you open the connection inside the scope.
Take a look at Tim Schreiber solution which is simple yet powerful and implemented using repository pattern and has Dapper Transactions in mind.
The Commit() in the code below shows it.
public class UnitOfWork : IUnitOfWork
{
private IDbConnection _connection;
private IDbTransaction _transaction;
private IBreedRepository _breedRepository;
private ICatRepository _catRepository;
private bool _disposed;
public UnitOfWork(string connectionString)
{
_connection = new SqlConnection(connectionString);
_connection.Open();
_transaction = _connection.BeginTransaction();
}
public IBreedRepository BreedRepository
{
get { return _breedRepository ?? (_breedRepository = new BreedRepository(_transaction)); }
}
public ICatRepository CatRepository
{
get { return _catRepository ?? (_catRepository = new CatRepository(_transaction)); }
}
public void Commit()
{
try
{
_transaction.Commit();
}
catch
{
_transaction.Rollback();
throw;
}
finally
{
_transaction.Dispose();
_transaction = _connection.BeginTransaction();
resetRepositories();
}
}
private void resetRepositories()
{
_breedRepository = null;
_catRepository = null;
}
public void Dispose()
{
dispose(true);
GC.SuppressFinalize(this);
}
private void dispose(bool disposing)
{
if (!_disposed)
{
if(disposing)
{
if (_transaction != null)
{
_transaction.Dispose();
_transaction = null;
}
if(_connection != null)
{
_connection.Dispose();
_connection = null;
}
}
_disposed = true;
}
}
~UnitOfWork()
{
dispose(false);
}
}
There are two intended ways to use transactions with Dapper.
Pass your IDbTranasction to your normal Dapper call.
Before:
var affectedRows = connection.Execute(sql, new {CustomerName = "Mark"});
After:
var affectedRows = connection.Execute(sql, new {CustomerName = "Mark"}, transaction=tx);
Use the new .Execute extension method that Dapper adds to IDbTransaction itself:
tx.Execute(sql, new {CustomerName = "Mark"});
Note: the variable tx comes from IDbTransaction tx = connection.BeginTransaction();
This is how you're supposed to use transactions with Dapper; neither of them are TranasctionScope.
Bonus Reading
https://stackoverflow.com/a/67474832/12597
I got this code:
try
{
using (OracleConnection c = new OracleConnection(globalDict[byAlias(connAlias)].connString))
{
c.Open();
using (OracleCommand recordExistentQuery = new OracleCommand("regular.IsExistent", c))
{
// here working on oraclecommand
}
}
} catch(Exception exc) { }
OracleConnection is class of devArt dotConnect for Oracle.
Will this code call c.Close() when it goes out of (OracleConnection c = new OracleConnection(globalDict[byAlias(connAlias)].connString)) { .... } ?
No, it will call Dipose(). A using block will implicitly call Dispose() on the object specified in the using statement.
But often times for a database connection, Dispose() handles the Close() functionality, releasing the connection/processId that keeps a connection.
I would also like to add that in the event of an exception somewhere in your //here working on oraclecommand (basically inside your using(...){ } statement, Dispose() will also be called.
By design, you should be able to make multiple to calls to an object implementing IDisposable. In your case, issuing a calling a call to Close() after your using block of code will simply do nothing, as the connection has already closed/been returned to the pool. Any additional calls after the object has cleaned up should just return and do nothing.
Using the TransactionScope object to set up an implicit transaction that doesn't need to be passed across function calls is great! However, if a connection is opened whilst another is already open, the transaction coordinator silently escalates the transaction to be distributed (needing MSDTC service to be running and taking up much more resources and time).
So, this is fine:
using (var ts = new TransactionScope())
{
using (var c = DatabaseManager.GetOpenConnection())
{
// Do Work
}
using (var c = DatabaseManager.GetOpenConnection())
{
// Do more work in same transaction using different connection
}
ts.Complete();
}
But this escalates the transaction:
using (var ts = new TransactionScope())
{
using (var c = DatabaseManager.GetOpenConnection())
{
// Do Work
using (var nestedConnection = DatabaseManager.GetOpenConnection())
{
// Do more work in same transaction using different nested connection - escalated transaction to distributed
}
}
ts.Complete();
}
Is there a recommended practise to avoid escalating transactions in this way, whilst still using nested connections?
The best I can come up with at the moment is having a ThreadStatic connection and reusing that if Transaction.Current is set, like so:
public static class DatabaseManager
{
private const string _connectionString = "data source=.\\sql2008; initial catalog=test; integrated security=true";
[ThreadStatic]
private static SqlConnection _transactionConnection;
[ThreadStatic] private static int _connectionNesting;
private static SqlConnection GetTransactionConnection()
{
if (_transactionConnection == null)
{
Transaction.Current.TransactionCompleted += ((s, e) =>
{
_connectionNesting = 0;
if (_transactionConnection != null)
{
_transactionConnection.Dispose();
_transactionConnection = null;
}
});
_transactionConnection = new SqlConnection(_connectionString);
_transactionConnection.Disposed += ((s, e) =>
{
if (Transaction.Current != null)
{
_connectionNesting--;
if (_connectionNesting > 0)
{
// Since connection is nested and same as parent, need to keep it open as parent is not expecting it to be closed!
_transactionConnection.ConnectionString = _connectionString;
_transactionConnection.Open();
}
else
{
// Can forget transaction connection and spin up a new one next time one's asked for inside this transaction
_transactionConnection = null;
}
}
});
}
return _transactionConnection;
}
public static SqlConnection GetOpenConnection()
{
SqlConnection connection;
if (Transaction.Current != null)
{
connection = GetTransactionConnection();
_connectionNesting++;
}
else
{
connection = new SqlConnection(_connectionString);
}
if (connection.State != ConnectionState.Open)
{
connection.Open();
}
return connection;
}
}
Edit: So, if the answer is to reuse the same connection when it's nested inside a transactionscope, as the code above does, I wonder about the implications of disposing of this connection mid-transaction.
So far as I can see (using Reflector to examine code), the connection's settings (connection string etc.) are reset and the connection is closed. So (in theory), re-setting the connection string and opening the connection on subsequent calls should "reuse" the connection and prevent escalation (and my initial testing agrees with this).
It does seem a little hacky though... and I'm sure there must be a best-practise somewhere that states that one should not continue to use an object after it's been disposed of!
However, since I cannot subclass the sealed SqlConnection, and want to maintain my transaction-agnostic connection-pool-friendly methods, I struggle (but would be delighted) to see a better way.
Also, realised that I could force non-nested connections by throwing exception if application code attempts to open nested connection (which in most cases is unnecessary, in our codebase)
public static class DatabaseManager
{
private const string _connectionString = "data source=.\\sql2008; initial catalog=test; integrated security=true; enlist=true;Application Name='jimmy'";
[ThreadStatic]
private static bool _transactionHooked;
[ThreadStatic]
private static bool _openConnection;
public static SqlConnection GetOpenConnection()
{
var connection = new SqlConnection(_connectionString);
if (Transaction.Current != null)
{
if (_openConnection)
{
throw new ApplicationException("Nested connections in transaction not allowed");
}
_openConnection = true;
connection.Disposed += ((s, e) => _openConnection = false);
if (!_transactionHooked)
{
Transaction.Current.TransactionCompleted += ((s, e) =>
{
_openConnection = false;
_transactionHooked = false;
});
_transactionHooked = true;
}
}
connection.Open();
return connection;
}
}
Would still value a less hacky solution :)
One of the primary reasons for transaction escalation is when you have multiple (different) connections involved in a transaction. This almost always escalates to a distributed transaction. And it is indeed a pain.
This is why we make sure that all our transactions use a single connection object. There are several ways to do this. For the most part, we use the thread static object to store a connection object, and our classes that do the database persistance work, use the thread static connection object (which is shared of course). This prevents multiple connections objects from being used and has eliminated transaction escalation. You could also achieve this by simply passing a connection object from method to method, but this isn't as clean, IMO.
I have a IDbConnection for both Sql or Oracle connections. I have no problem to open it and then read data or save data through the connection. However, when the job is done, I tried to close the connection. Then I got a exception: "Internal .Net Framework Data Provider error 1".
Here are some codes to close the connection:
if (conn != null) // conn is IDbConnectin
{
if (conn.State == System.Data.ConnectionState.Open)
{
conn.Close(); // bung! exception
}
conn.Dispose();
}
conn = null;
Anything else I should check before safely closing the connection?
I know it might not sound like it solves your problem directly, but IDbConnection is IDisposable, so wrap your code that uses it in a using {} block.
Why?
You probably know that at the end of a using {} block, Dispose() is called. And, in every instance of IDbConnection, calling Dispose() will indirectly call Close(). But you get an additional bonus to using using that'll prevent you from running into this issue entirely -- by using using, you're forced to keep the creation, opening, closing, and disposal of the connection within the same context.
Most problems I found where people were running into your issue is when they use a Finalizer, or a separate thread to dispose of their connection objects. To me, there's an even bigger smell going on, where they're keeping their disposable objects alive for just a little bit too long, possibly sharing the connection between multiple members of the same class.
In other words, when you pass around the connection object, you might be tempted to write something like this:
class AccountService {
private IDbConnection conn;
internal AccountService(IDbConnection connection) {
this.conn = connection;
}
public Account GetAccount(String id) {
IDbCommand command = conn.CreateCommand();
conn.Open;
Account a = Account.FromReader(command.Execute(Strings.AccountSelect(id)));
conn.Close; // I remembered to call Close here
return a;
}
// ... other methods where I Open() and Close() conn
// hopefully not necessary since I've been careful to call .Close(), but just in case I forgot or an exception occured
~AccountService() {
if (conn != null)
{
if (conn.State == System.Data.ConnectionState.Open)
{
conn.Close();
}
conn.Dispose();
}
conn = null;
}
}
If you had used using, you wouldn't have even needed to think about using a Finalizer:
// IDbFactory is custom, and used to retrieve a Connection for a given Database
interface IDbFactory {
IDbConnection Connection { get; }
}
class AccountService {
private IDbFactory dbFactory;
internal AccountService(IDbFactory factory) {
this.dbFactory = factory;
}
public Account GetAccount(String id) {
using (IDbConnection connection = dbFactory.Connection) {
using (command = connection.GetCommand()) {
connection.Open();
return Account.FromReader(command.Execute(Strings.AccountSelect(id)));
}
} // via using, Close and Dispose are automatically called
}
// I don't need a finalizer, because there's nothing to close / clean up
}
There are exceptions to the using rule, especially if the construction of the disposable object is expensive, but 99 times out of 100, if you're not using using, there's a smell.
I think you call close method in other thread or in Finilize method. 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. see here