Click here to Skip to main content
15,887,485 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 542.7K   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.Maps
{
	using Kerosene.Tools;
	using System;
	using System.Collections;
	using System.Collections.Generic;
	using System.Text;

	// ==================================================== 
	/// <summary>
	/// Represents a member of the type that is hidden to the map matching mechanism. This class is used to identify
	/// the members that the application does not want to participate in the tranfer of information back and forth
	/// the database, even if there is a column in the database whose name matches the one of the given member.
	/// </summary>
	public class KMapHiddenMember<T> : IKMapHiddenMember where T : class
	{
		KMetaMap<T> _MetaMap = null;
		string _Name = null;

		internal KMapHiddenMember(KMetaMap<T> map, string name)
		{
			_MetaMap = map;
			_Name = name;
		}
		
		internal void OnDispose()
		{
			_MetaMap = null;
		}
		
		internal KMapHiddenMember<T> OnClone(KMetaMap<T> newmap)
		{
			var cloned = new KMapHiddenMember<T>(newmap, _Name);
			return cloned;
		}

		/// <summary>
		/// Returns the string representation of this instance.
		/// </summary>
		public override string ToString()
		{
			StringBuilder sb = new StringBuilder();
			if (_MetaMap == null) sb.Append("disposed::[");

			sb.Append(_Name ?? "-");

			if (_MetaMap == null) sb.Append("]");
			return sb.ToString();
		}

		/// <summary>
		/// The map this instance belongs to.
		/// </summary>
		public KMetaMap<T> MetaMap
		{
			get { return _MetaMap; }
		}
		IKMetaMap IKMapHiddenMember.MetaMap
		{
			get { return this.MetaMap; }
		}

		/// <summary>
		/// The name of the hidden member in the type.
		/// </summary>
		public string Name
		{
			get { return _Name; }
		}
	}

	// ==================================================== 
	/// <summary>
	/// Represents the collection of members of the type that are hidden to the map matching mechanism. This class is
	/// used to identify the members that the application does not want to participate in the tranfer of information
	/// back and forth the database, even if there are columns in the database whose names match the one of the given
	/// members.
	/// </summary>
	public class KMapHiddenMemberCollection<T> : IKMapHiddenMemberCollection where T : class
	{
		KMetaMap<T> _MetaMap = null;
		List<KMapHiddenMember<T>> _List = new List<KMapHiddenMember<T>>();

		internal KMapHiddenMemberCollection(KMetaMap<T> map)
		{
			_MetaMap = map;
		}
		
		internal void OnDispose()
		{
			foreach (var entry in _List) entry.OnDispose(); _List.Clear();
			_MetaMap = null;
		}
		
		internal KMapHiddenMemberCollection<T> OnClone(KMetaMap<T> newmap)
		{
			var cloned = new KMapHiddenMemberCollection<T>(newmap);
			foreach (var entry in _List) cloned._List.Add(entry.OnClone(newmap));
			return cloned;
		}

		/// <summary>
		/// Returns the string representation of this instance.
		/// </summary>
		public override string ToString()
		{
			StringBuilder sb = new StringBuilder();
			if (_MetaMap == null) sb.Append("disposed::[");

			if (Count == 0) sb.Append("-");
			else
			{
				bool first = true; foreach (var entry in _List)
				{
					if (first) first = false; else sb.Append(", ");
					sb.Append(entry);
				}
			}

			if (_MetaMap == null) sb.Append("]");
			return sb.ToString();
		}

		/// <summary>
		/// The map this instance belongs to.
		/// </summary>
		public KMetaMap<T> MetaMap
		{
			get { return _MetaMap; }
		}
		IKMetaMap IKMapHiddenMemberCollection.MetaMap
		{
			get { return this.MetaMap; }
		}

		/// <summary>
		/// Adds a new entry into this collection.
		/// <para>Returns the new entry that has been created to permit a fluent syntax chaining.</para>
		/// <para>This method fails if the map is already validated.</para>
		/// </summary>
		/// <param name="name">A dynamic lambda expression resolving into the name of the hidden member.</param>
		public KMapHiddenMember<T> Add(Func<dynamic, object> name)
		{
			if (_MetaMap == null) throw new ObjectDisposedException(this.ToString());
			if (_MetaMap.IsDisposed) throw new ObjectDisposedException(_MetaMap.ToString());
			if (_MetaMap.IsValidated) throw new InvalidOperationException(string.Format("Map '{0}' is already validated.", _MetaMap));
			if (name == null) throw new ArgumentNullException("name", "Specification cannot be null.");

			var str = _MetaMap.MetaLink.Link.Parser.Parse(name);
			str = str.Validated("Name");

			var entry = _List.Find(x => x.Name == str);
			if (entry != null) throw new DuplicateException(string.Format(
				"Member '{0}' already registered in map '{1}'", str, _MetaMap));

			var info = DynamicInfo.GetDynamicInfo<T>(name);
			if (info == null) throw new NotFoundException(string.Format(
				 "Member '{0}' not found on type '{1}'.", str, typeof(T).EasyName()));

			entry = new KMapHiddenMember<T>(_MetaMap, str); _List.Add(entry);
			return entry;
		}
		IKMapHiddenMember IKMapHiddenMemberCollection.Add(Func<dynamic, object> name)
		{
			return this.Add(name);
		}

		/// <summary>
		/// Removes the given entry from this collection. Returns true if the entry has been removed sucessfully or
		/// false otherwise.
		/// </summary>
		/// <param name="entry">The entry to remove from this collection.</param>
		public bool Remove(KMapHiddenMember<T> entry)
		{
			if (_MetaMap == null) throw new ObjectDisposedException(this.ToString());
			if (_MetaMap.IsDisposed) throw new ObjectDisposedException(_MetaMap.ToString());
			if (_MetaMap.IsValidated) throw new InvalidOperationException(string.Format("Map '{0}' is already validated.", _MetaMap));
			if (entry == null) throw new ArgumentNullException("entry", "Entry cannot be null.");

			bool r = _List.Remove(entry); if (r) entry.OnDispose();
			return r;
		}
		bool IKMapHiddenMemberCollection.Remove(IKMapHiddenMember entry)
		{
			return this.Remove((KMapHiddenMember<T>)entry);
		}

		/// <summary>
		/// Gets the number of entries in this collection.
		/// </summary>
		public int Count
		{
			get { return _List == null ? 0 : _List.Count; }
		}

		/// <summary>
		/// Returns the first entry in this collection that matches the conditions given in the predicate, or null
		/// if no such entry can be found.
		/// </summary>
		/// <param name="match">The predicate that defines the conditions of the entry to look for.</param>
		public KMapHiddenMember<T> Find(Predicate<KMapHiddenMember<T>> match)
		{
			if (_MetaMap == null) throw new ObjectDisposedException(this.ToString());
			if (_MetaMap.IsDisposed) throw new ObjectDisposedException(_MetaMap.ToString());
			if (match == null) throw new ArgumentNullException("match", "Predicate cannot be null.");

			return _List.Find(match);
		}
		IKMapHiddenMember IKMapHiddenMemberCollection.Find(Predicate<IKMapHiddenMember> match)
		{
			return this.Find(match);
		}

		public IEnumerator<KMapHiddenMember<T>> GetEnumerator()
		{
			if (_MetaMap == null) throw new ObjectDisposedException(this.ToString());
			if (_MetaMap.IsDisposed) throw new ObjectDisposedException(_MetaMap.ToString());

			return _List.GetEnumerator();
		}
		IEnumerator<IKMapHiddenMember> IEnumerable<IKMapHiddenMember>.GetEnumerator()
		{
			return this.GetEnumerator();
		}
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}
	}
}
// ======================================================== 

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