Click here to Skip to main content
15,896,557 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.9K   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.Core.Concrete
{
	using Kerosene.Tools;
	using System;
	using System.Collections;

	// ==================================================== 
	/// <summary>
	/// Represents a command whose contents can be set explicitly using any arbitrary text and parameters.
	/// <para>
	/// This class is provided to support specialized scenarios not covered by the standard methods of the other
	/// command types, and it can also be used to invoke stored procedures.
	/// </para>
	/// </summary>
	public class KCommandRawBase : KCommandBase, IKCommandRaw
	{
		protected string DataText = null;

		/// <summary>
		/// Create a new raw command.
		/// </summary>
		/// <param name="link">The link this command will be associated with.</param>
		public KCommandRawBase(IKLink link) : base(link) { }

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

		/// <summary>
		/// Returns a new instance that is a copy of this original one.
		/// </summary>
		public KCommandRawBase Clone()
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			var cloned = new KCommandRawBase(this.Link);
			OnClone(cloned); return cloned;
		}
		IKCommandRaw IKCommandRaw.Clone()
		{
			return this.Clone();
		}
		IKCommand IKCommand.Clone()
		{
			return this.Clone();
		}
		object ICloneable.Clone()
		{
			return this.Clone();
		}

		protected override void OnClone(object cloned)
		{
			var temp = (KCommandRawBase)cloned;

			base.OnClone(temp);
			temp.DataText = DataText;
		}

		/// <summary>
		/// Returns a new instance that is a copy of this original one, but associated with the new link reference
		/// given.
		/// </summary>
		/// <param name="newlink">The link reference the new cloned instance will be associated with.</param>
		public KCommandRawBase Clone(IKLink newlink)
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			var cloned = new KCommandRawBase(newlink);
			OnClone(cloned); return cloned;
		}
		IKCommandRaw IKCommandRaw.Clone(IKLink link)
		{
			return this.Clone(link);
		}
		IKCommand IKCommand.Clone(IKLink link)
		{
			return this.Clone(link);
		}
		object ICloneableWithLink.Clone(IKLink link)
		{
			return this.Clone(link);
		}

		/// <summary>
		/// Returns an enumerator object able to execute this command.
		/// </summary>
		public IKEnumerator GetEnumerator()
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			return Link.CreateEnumerator(this);
		}
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		/// <summary>
		/// Returns an executor object able to execute this command.
		/// </summary>
		public IKExecutor GetExecutor()
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			return Link.CreateExecutor(this);
		}

		/// <summary>
		/// Generates an string containing the actual text of the command to be executed in the syntax understood
		/// by the underlying database.
		/// </summary>
		/// <param name="iterable">Whether to produce the iterable version of the command, or the non-iterable one.</param>
		public override string GenerateCommandText(bool iterable)
		{
			return DataText ?? string.Empty;
		}

		/// <summary>
		/// Sets the new contents of this command using the text given and the optional list of parameters.
		/// <para>Returns this instance to permit a fluent syntax chaining.</para>
		/// </summary>
		/// <param name="text">The new text of this command.</param>
		/// <param name="args">An optional collection with the values of the arguments specified in the text. The
		/// parameters shall be specified in the text using the standard positional '{n}' placeholder.</param>
		public KCommandRawBase Set(string text, params object[] args)
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());

			DataText = null;
			Parameters.Clear();
			return this.Append(text, args);
		}
		IKCommandRaw IKCommandRaw.Set(string text, params object[] args)
		{
			return this.Set(text, args);
		}

		/// <summary>
		/// Sets the new contents of this command parsing the dynamic lambda expression given that resolves into
		/// the logic of this command.
		/// <para>Returns this instance to permit a fluent syntax chaining.</para>
		/// </summary>
		/// <param name="specs">A dynamic lambda expression that resolves into the logic of the command.</param>
		public KCommandRawBase Set(Func<dynamic, object> specs)
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());

			DataText = null;
			Parameters.Clear();
			return this.Append(specs);
		}
		IKCommandRaw IKCommandRaw.Set(Func<dynamic, object> specs)
		{
			return this.Set(specs);
		}

		/// <summary>
		/// Appends to the previous contents of the command the ones obtained using the text given and the optional
		/// list of parameters.
		/// <para>An space character is injected, if needed, as a separator between the previous and new contents.</para>
		/// <para>Returns this instance to permit a fluent syntax chaining.</para>
		/// </summary>
		/// <param name="text">The new text of this command.</param></param>
		/// <param name="args">An optional collection with the values of the arguments specified in the text. The
		/// parameters shall be specified in the text using the standard positional '{n}' placeholder.</param>
		public KCommandRawBase Append(string text, params object[] args)
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			if (text == null) throw new ArgumentNullException("text", "Command text cannot be null.");

			if (args != null)
			{
				for (int i = 0; i < args.Length; i++)
				{
					if (args[i] is IKParameter) throw new ArgumentException(
						 string.Format("Argument #{0}: '{1}' cannot be a IKParameter instance.", i, args[i].Sketch()));

					var par = Parameters.AddCreate(args[i]);
					var old = string.Format("{{{0}}}", i);
					text = text.Replace(old, par.Name);
				}
			}

			bool space = text.StartsWith(" ");
			DataText = DataText == null ? text : string.Format("{0}{1}{2}", DataText, space ? string.Empty : " ", text);
			return this;
		}
		IKCommandRaw IKCommandRaw.Append(string text, params object[] args)
		{
			return this.Append(text, args);
		}

		/// <summary>
		/// Appends to the contents of this command the ones obtained by parsing the dynamic lambda expression given
		/// that resolves into the logic to append to this command.
		/// <para>An space character is injected, if needed, as a separator between the previous and new contents.</para>
		/// <para>Returns this instance to permit a fluent syntax chaining.</para>
		/// </summary>
		/// <param name="specs">A dynamic lambda expression that resolves into the logic to append to the command.</param>
		public KCommandRawBase Append(Func<dynamic, object> specs)
		{
			if (IsDisposed) throw new ObjectDisposedException(this.ToString());
			if (specs == null) throw new ArgumentNullException("spec", "Specification cannot be null.");

			var text = Link.Parser.Parse(specs, Parameters);

			bool space = text.StartsWith(" ");
			DataText = DataText == null ? text : string.Format("{0}{1}{2}", DataText, space ? string.Empty : " ", text);
			return this;
		}
		IKCommandRaw IKCommandRaw.Append(Func<dynamic, object> specs)
		{
			return this.Append(specs);
		}
	}
}
// ======================================================== 

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