Click here to Skip to main content
15,897,371 members
Articles / Programming Languages / SQL

DataLoaders - Unified Data to Object Binding

Rate me:
Please Sign up or sign in to vote.
4.72/5 (35 votes)
31 Oct 2004CPOL19 min read 76.3K   2.9K   83  
A framework to completely separate objects from their data source - allowing any data source to be used without prior consideration in your code or designs. Databases, text files, web services and potentially anything else can all be used or swapped transparently.
using System;
using System.Data;
using System.Collections;

namespace Bttlxe.Data
{
	/// <summary>
	///  A strongly typed collection of key-and-value pairs for <see cref="DataItem"/> fields.
	/// </summary>
	/// <remarks>
	/// <p>The <b>foreach</b> statement of the C# language (<b>for each</b> in Visual Basic) requires the type of
	/// each element in the collection. Since each element of the <see cref="DataItemDictionary"/> is a key-and-value
	/// pair, the element type is not the type of the key or the type of the value. Instead, the element type is
	/// <see cref="DictionaryEntry"/>. For example:</p>
	/// <code>foreach (DictionaryEntry myDE in myDataItemDictionary) {...}</code>
	/// <p> The <b>foreach</b> statement is a wrapper around the enumerator, which only allows reading from, not
	/// writing to, the collection.</p>
	/// <p><see cref="DataItemDictionary"/> collections can be serialised.</p>
	///  <seealso cref="DataItem"/>
	/// </remarks>
	[Serializable()]
	public class DataItemDictionary : DictionaryBase  
	{
		#region DictionaryBase Members

		#region Properties

		/// <summary>
		/// Gets or sets the value associated with the specified key.
		/// </summary>
		/// <param name="key">The key whose value to get or set.</param>
		/// <value>
		/// The value associated with the specified key. If the specified key is not found, attempting to get
		/// it returns a null reference (<see cref="Nothing"/> in Visual Basic), and attempting to set it creates
		/// a new element using the specified key.
		/// </value>
		/// <remarks>
		/// <p>This property provides the ability to access a specific element in the collection by using the
		/// following syntax: <c>myCollection[key]</c>.</p>
		/// <p>When setting this property, if the specified key already exists in the <see cref="DataItemDictionary"/>,
		/// the value is replaced; otherwise, a new element is created. In contrast, the <see cref="Add"/> method does
		/// not modify existing elements.</p>
		/// </remarks>
		public string this[string key]  
		{
			get
			{
				return (string)Dictionary[key];
			}
			set
			{
				Dictionary[key] = value;
			}
		}

		/// <summary>
		/// Gets an <see cref="ICollection"/> containing the keys in the <see cref="DataItemDictionary"/>.
		/// </summary>
		/// <value>
		/// An <see cref="ICollection"/> containing the keys in the <see cref="DataItemDictionary"/>.
		/// </value>
		/// <remarks>
		/// <p>The order of the keys in the <see cref="ICollection"/> is unspecified, but it is the same order
		/// as the associated values in the <see cref="ICollection"/> returned by the <see cref="Values"/> property.</p>
		/// <p>The returned <see cref="ICollection"/> is not a static copy; instead, the <see cref="ICollection"/>
		/// refers back to the keys in the original <see cref="DictionaryBase"/>. Therefore, changes to the
		/// <see cref="DictionaryBase"/> continue to be reflected in the returned ICollection.</p>
		/// </remarks>
		public ICollection Keys  
		{
			get
			{
				return Dictionary.Keys;
			}
		}

		/// <summary>
		/// Gets an <see cref="ICollection"/> containing the values in the <see cref="DataItemDictionary"/>.
		/// </summary>
		/// <value>
		/// An <see cref="ICollection"/> containing the values in the <see cref="DataItemDictionary"/>.
		/// </value>
		/// <remarks>
		/// <p>The order of the values in the <see cref="ICollection"/> is unspecified, but it is the same
		/// order as the associated keys in the <see cref="ICollection"/> returned by the <see cref="Keys"/>
		/// method.</p>
		/// <p>The returned <see cref="ICollection"/> is not a static copy; instead, the <see cref="ICollection"/>
		/// refers back to the values in the original <see cref="DictionaryBase"/>. Therefore, changes to the
		/// <see cref="DictionaryBase"/> continue to be reflected in the returned <see cref="ICollection"/>.</p>
		/// </remarks>
		public ICollection Values  
		{
			get
			{
				return Dictionary.Values;
			}
		}

		#endregion

		/// <summary>
		/// Adds an element with the specified key and value into the <see cref="DataItemDictionary"/>.
		/// </summary>
		/// <param name="key">The key of the element to add.</param>
		/// <param name="value">The value of the element to add.</param>
		/// <remarks>
		/// <p>An object that has no correlation between its state and its hash code value should typically not
		/// be used as the key. For example, <see cref="String"/> objects are better than <see cref="StringBuilder"/>
		/// objects for use as keys.</p>
		/// <p>The <see cref="Item"/> property can also be used to add new elements by setting the value of a key
		/// that does not exist in the <see cref="DataItemDictionary"/>. For example:
		///   <c>myCollection["myNonexistentKey"] = myValue</c>. However, if the specified key already exists in the
		///   <see cref="DataItemDictionary"/>, setting the <see cref="Item"/> property overwrites the old value. In
		///   contrast, the <see cref="Add"/> method does not modify existing elements.</p>
		/// </remarks>
		public void Add(string key, String value)  
		{
			Dictionary.Add(key, value);
		}

		/// <summary>
		/// Determines whether the <see cref="DataItemDictionary"/> contains a specific key.
		/// </summary>
		/// <param name="key">The key to locate in the <see cref="DataItemDictionary"/>.</param>
		/// <returns><b>true</b> if the <see cref="DataItemDictionary"/> contains an element with the specified key;
		/// otherwise, <b>false</b>.</returns>
		public bool Contains(string key)  
		{
			return Dictionary.Contains(key);
		}

		/// <summary>
		/// Removes the element with the specified key from the <see cref="DataItemDictionary"/>.
		/// </summary>
		/// <param name="key">The key of the element to remove.</param>
		/// <remarks>
		/// If the <see cref="DataItemDictionary"/> does not contain an element with the specified key, the
		/// <see cref="DataItemDictionary"/> remains unchanged. No exception is thrown.
		/// </remarks>
		public void Remove(string key)  
		{
			Dictionary.Remove(key);
		}

		/// <summary>
		/// Performs additional custom processes before inserting a new element into the underlying
		/// <see cref="DictionaryBase"/> instance.
		/// </summary>
		/// <param name="key">The key of the element to insert.</param>
		/// <param name="value">The value of the element to insert.</param>
		protected override void OnInsert(Object key, Object value)  
		{
			if (key.GetType() != Type.GetType("System.String"))
				throw new ArgumentException("key must be of type System.String.", "key");

			if (value.GetType() != Type.GetType("System.String"))
				throw new ArgumentException( "value must be of type String.", "value" );
		}

		/// <summary>
		/// Performs additional custom processes before removing an element from the underlying
		/// <see cref="DictionaryBase"/> instance.
		/// </summary>
		/// <param name="key">The key of the element to remove.</param>
		/// <param name="value">The value of the element to remove.</param>
		protected override void OnRemove(Object key, Object value)  
		{
			if (key.GetType() != Type.GetType("System.String"))
				throw new ArgumentException("key must be of type System.String.", "key");
		}

		/// <summary>
		/// Performs additional custom processes before setting a value in the underlying
		/// <see cref="DictionaryBase"/> instance.
		/// </summary>
		/// <param name="key">The key of the element to locate.</param>
		/// <param name="oldValue">The old value of the element associated with key.</param>
		/// <param name="newValue">The new value of the element associated with key.</param>
		protected override void OnSet(Object key, Object oldValue, Object newValue)  
		{
			if (key.GetType() != Type.GetType("System.String") )
				throw new ArgumentException("key must be of type System.String.", "key");

			if (newValue.GetType() != Type.GetType("System.String"))
				throw new ArgumentException("newValue must be of type System.String.", "newValue");
		}

		/// <summary>
		/// Performs additional custom processes when validating the element with the specified key and value.
		/// </summary>
		/// <param name="key">The key of the element to validate.</param>
		/// <param name="value">The value of the element to validate.</param>
		protected override void OnValidate(Object key, Object value)  
		{
			if (key.GetType() != Type.GetType("System.String"))
				throw new ArgumentException("key must be of type System.String.", "key");

			if (value.GetType() != Type.GetType("System.String"))
				throw new ArgumentException("value must be of type System.String.", "value");
		}

		#endregion
	}

	/// <summary>
	/// <p>A wrapper around a <see cref="DataSet"/> for transporting data between a data loader and a
	/// data user.</p>
	/// </summary>
	/// <remarks>
	/// <p>Data items are objects that can represent themselves as a <see cref="DataSet"/> with optional sorting
	/// or conditional statements.  A data item should not be treated as a data source as it is designed solely
	/// for the transportation of data between loaders and a data user (which may or may not be the object implementing
	/// the interface).</p>
	/// <p>Framework objects implementing <see cref="IDataItem"/> are shown in the table below:</p>
	/// <list type="table">
	///   <listheader>
	///     <term>Object</term>
	///     <description>Description</description>
	///   </listheader>
	///   <item>
	///     <term><see cref="DataItem"/></term>
	///     <description>A generic implementation of a data item for handling custom objects.</description>
	///   </item>
	///   <item>
	///     <term><see cref="News"/></term>
	///     <description>A news item represents some common fields used with news releases.</description>
	///   </item>
	///   <item>
	///     <term><see cref="NewsList"/></term>
	///     <description>A list of <see cref="News"/> objects.</description>
	///   </item>
	/// </list>
	/// <p>Objects implementing <see cref="IDataItem"/> objects which are serialisable should either implement the
	/// <see cref="Data"/> property with the <see cref="NonSerializedAttribute"/> or else hide its own data properties
	/// to prevent possible dupication.</p>
	/// <seealso cref="DataItemDictionary"/>
	/// <seealso cref="IDataLoader"/>
	/// </remarks>
	/// <example>
	/// <p>For an example of a data item refer to the following example which demonstrates the correct usage of a data
	/// loader and data item.  (Note that the example uses the interfaces themselves to show the concept, you must
	/// substitute them for objects implementing them in your own code.)</p>
	/// <p class="lang">[C#]</p>
	/// <code>
	/// IDataLoader oLoader = new IDataLoader();
	/// IDataItem oItem = new IDataItem();
	///	oLoader.Execute(ref oItem, DataOperation.Read);
	/// </code>
	/// </example>
	public interface IDataItem
	{
		/// <summary>
		/// The data set.
		/// </summary>
		DataSet Data
		{
			get;
			set;
		}

		/// <summary>
		/// A data set containing the schema for this object.
		/// </summary>
		DataSet Schema
		{
			get;
		}

		/// <summary>
		/// The condition clause.
		/// </summary>
		/// <value>
		/// A T-SQL condition clause.
		/// </value>
		string Condition
		{
			get;
			set;
		}

		/// <summary>
		/// The sort string.
		/// </summary>
		/// <value>
		/// A T-SQL ORDER BY string.
		/// </value>
		string Sort
		{
			get;
			set;
		}
	}
}

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
CEO Bttlxe Ltd & Incentica Ltd
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions