Click here to Skip to main content
15,896,359 members
Articles / Hosted Services / Azure

Kerosene ORM: a dynamic, configuration-less and self-adaptive ORM for POCO objects supporting a SQL-like syntax from C#

Rate me:
Please Sign up or sign in to vote.
4.96/5 (71 votes)
1 Mar 2015CPOL35 min read 548.8K   4.6K   212  
The seventh version of the dynamic, configuration-less and self-adaptive Kerosene ORM library, that provides full real support for POCO objects, natural SQL-like syntax from C#, and advanced capabilities while being extremely easy to use.
// ======================================================== 
namespace Kerosene.ORM.Direct.Concrete
{
	using Kerosene.ORM.Core;
	using Kerosene.ORM.Core.Concrete;
	using System;
	using System.Data;
	using System.Transactions;

	// ==================================================== 
	/// <summary>
	/// Represents a nestable transaction in a direct connection scenario.
	/// </summary>
	public class KTransactionDirect : KTransactionBase, IKTransactionDirect
	{
		IDbTransaction _DbTransaction = null;
		TransactionScope _TransactionScope = null;
		bool _LinkOpenedByTransaction = false;
		int _Level = 0;

		internal KTransactionDirect(IKLinkDirect link, KTransactionMode mode) : base(link, mode) { }

		protected override void OnDispose(bool disposing)
		{
			if (!IsDisposed && disposing) { }
			base.OnDispose(disposing);
		}

		/// <summary>
		/// Gets the direct link this transaction is associated with.
		/// </summary>
		public new IKLinkDirect Link
		{
			get { return (IKLinkDirect)base.Link; }
		}
		IKLink IKTransaction.Link
		{
			get { return this.Link; }
		}

		/// <summary>
		/// Gets the active database transaction in use by this instance, or null.
		/// </summary>
		public IDbTransaction DbTransaction
		{
			get { return _DbTransaction; }
		}

		/// <summary>
		/// Gets the active transaction scope in use by this instance, or null.
		/// </summary>
		public TransactionScope TransactionScope
		{
			get { return _TransactionScope; }
		}

		/// <summary>
		/// Starts a new physical transaction, or if it was already active, increases its nesting level.
		/// </summary>
		public override void Start()
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			if (Link == null) throw new InvalidOperationException(string.Format("This '{0}' is not associated with any link.", this));
			if (Link.IsDisposed) throw new ObjectDisposedException(Link.ToString());

			if (_Level > 0) _Level++;
			else
			{
				if (Mode == KTransactionMode.Database)
				{
					if (!Link.IsOpen) { Link.Open(); _LinkOpenedByTransaction = true; }
					_DbTransaction = Link.Connection.BeginTransaction();
				}
				if (Mode == KTransactionMode.GlobalScope)
				{
					_TransactionScope = new TransactionScope();
					if (!Link.IsOpen) { Link.Open(); _LinkOpenedByTransaction = true; }
				}
				_Level = 1;
			}
		}

		/// <summary>
		/// Commits the underlying physical transaction, or if it nesting level is greater than one, decreases it.
		/// <para>This method is merely ignored is the transaction was not active.</para>
		/// </summary>
		public override void Commit()
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			if (Link == null) throw new InvalidOperationException(string.Format("This '{0}' is not associated with any link.", this));
			if (Link.IsDisposed) throw new ObjectDisposedException(Link.ToString());

			if (_Level == 0) return;
			if (_Level == 1)
			{
				if (Mode == KTransactionMode.Database)
				{
					_DbTransaction.Commit(); _DbTransaction.Dispose(); _DbTransaction = null;
					if (_LinkOpenedByTransaction) { Link.Close(); _LinkOpenedByTransaction = false; }
				}
				if (Mode == KTransactionMode.GlobalScope)
				{
					_TransactionScope.Complete(); _TransactionScope.Dispose(); _TransactionScope = null;
					if (_LinkOpenedByTransaction) { Link.Close(); _LinkOpenedByTransaction = false; }
				}
				_Level = 0;
			}
			else _Level--;
		}

		/// <summary>
		/// Aborts the underlying physical transaction regardless of the nesting level of this instance.
		/// <para>This method is merely ignored is the transaction was not active.</para>
		/// </summary>
		public override void Abort()
		{
			if (IsDisposed) return;
			if (Link == null || Link.IsDisposed) return;

			if (_DbTransaction != null)
			{
				_DbTransaction.Rollback(); _DbTransaction.Dispose(); _DbTransaction = null;
				if (_LinkOpenedByTransaction) Link.Close();
			}
			if (_TransactionScope != null)
			{
				_TransactionScope.Dispose(); _TransactionScope = null;
				if (_LinkOpenedByTransaction) Link.Close();
			}

			_LinkOpenedByTransaction = false;
			_Level = 0;
		}

		/// <summary>
		/// Gets the nesting level of this transaction. A value of cero indicates that this transaction is not
		/// active.
		/// </summary>
		public override int Level
		{
			get { return _Level; }
		}
	}
}
// ======================================================== 

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Spain Spain
mbarbac has worked in start-ups, multinational tech companies, and consulting ones, serving as CIO, CTO, SW Development Director, and Consulting Director, among many other roles.

Solving complex puzzles and getting out of them business value has ever been among his main interests - and that's why he has spent his latest 25 years trying to combine his degree in Theoretical Physics with his MBA... and he is still trying to figure out how all these things can fit together.

Even if flying a lot across many countries, along with the long working days that are customary in IT management and Consultancy, he can say that, after all, he lives in Spain (at least the weekends).

Comments and Discussions