public override bool ContainsValue(DbConnectionProvider value) {
				lock (root)
					return list.ContainsValue(value);
			}
		/// <summary>
		/// Loads a config file into a XMLDocument and populates a DBConnectionTypes collection of the 
		/// database connection details found in the config file. 
		/// </summary>
		/// <param name="config">The name (and path) of a config file containing <connection> elements</param>
		/// <returns>A Collection of Connection Types</returns>
		private DbConnectionTypes LoadConfig ( string config ) {

			try {
				this.ReadXml(config);
				DbConnectionTypes connectionTypes = new DbConnectionTypes();
				DataRow connectionsRow = this.Tables["connections"].Rows[0];

				// Read the available connections from the connections collection
				// --------------------------------------------------------------
				foreach (DataRow connectionRow in connectionsRow.GetChildRows("connections_connection")) {

					DbConnectionType connectionType = new DbConnectionType();
					connectionType.Name = connectionRow["name"].ToString();
					connectionType.DbTypeName = connectionRow["type"].ToString();
					connectionType.InternalProviderName = connectionRow["internalProvider"].ToString();

					// Read the Settings for this connection type
					// --------------------------------------------------------------
					foreach (DataRow settingsRow in connectionRow.GetChildRows("connection_settings")) {
						if (settingsRow.Table.Columns.Contains("file"))		{
							connectionType.SupportsFile = GetSettingState(settingsRow["file"].ToString(),false);
							connectionType.PromptFile   = GetSettingValue(settingsRow["file"].ToString());
						}
						if (settingsRow.Table.Columns.Contains("server"))		{
							connectionType.SupportsServer = GetSettingState(settingsRow["server"].ToString(),true);
							connectionType.PromptServer   = GetSettingValue(settingsRow["server"].ToString());
						}
						if (settingsRow.Table.Columns.Contains("name"))		{
							connectionType.SupportsName = GetSettingState(settingsRow["name"].ToString(),true);
							connectionType.PromptName   = GetSettingValue(settingsRow["name"].ToString());
						}
						if (settingsRow.Table.Columns.Contains("userid"))		{
							connectionType.SupportsUserID = GetSettingState(settingsRow["userid"].ToString(),true);
							connectionType.PromptUserID   = GetSettingValue(settingsRow["userid"].ToString());
						}
						if (settingsRow.Table.Columns.Contains("password"))		{
							connectionType.SupportsPassword = GetSettingState(settingsRow["password"].ToString(),true);
							connectionType.PromptPassword   = GetSettingValue(settingsRow["password"].ToString());
						}
						if (settingsRow.Table.Columns.Contains("filter"))		{
							connectionType.SupportsFilter = GetSettingState(settingsRow["filter"].ToString(),false);
							connectionType.PromptFilter   = GetSettingValue(settingsRow["filter"].ToString());
						}
					}

					// Read each of the Providers Details
					// --------------------------------------------------------------
					foreach (DataRow providersRow in connectionRow.GetChildRows("connection_providers")) {
						foreach (DataRow providerRow in providersRow.GetChildRows("providers_provider")) {

							DbConnectionProvider connectionProvider = new DbConnectionProvider();
							connectionProvider.Name = providerRow["name"].ToString();
							connectionProvider.ProviderTypeName = providerRow["type"].ToString();
							connectionProvider.Parent = connectionType;
							connectionProvider.Template = Regex.Replace(providerRow["provider_Text"].ToString(), @"[\r\t\n]", "");

							if (providerRow.Table.Columns.Contains("allowEmptyParameters")) connectionProvider.AllowEmptyParameters = GetSettingState(providerRow["allowEmptyParameters"].ToString(), true);
							if (providerRow.Table.Columns.Contains("enabled")) connectionProvider.Enabled = GetSettingState(providerRow["enabled"].ToString(),true);
							if (providerRow.Table.Columns.Contains("fileMask")) connectionProvider.FileMask = providerRow["fileMask"].ToString();

							connectionType.Providers.Add(connectionProvider); 
						}
					}
					connectionTypes.Add(connectionType);
				}
				return connectionTypes;
			}
			catch (Exception ex) {
				throw new ApplicationException(String.Format("Could not reference the ProviderConfig.xml configuration file: {0}\n{1}", config, ex.Message));
			}
		}
		private void Insert(int index, string key, DbConnectionProvider value) {
			if (count == keys.Length)
				EnsureCapacity(count + 1);

			if (index < count) {
				Array.Copy(keys, index, keys, index + 1, count - index);
				Array.Copy(values, index, values, index + 1, count - index);
			}

			keys[index] = key;
			values[index] = value;
			count++;
			version++;
		}
			public override void Add(string key, DbConnectionProvider value) {
				lock (root)
					list.Add(key, value);
			}
		/// <summary>
		///		Removes the element at the specified index of the <b>DbConnectionProviders</b>.
		/// </summary>
		/// <param name="index">The zero-based index of the element to remove.</param>
		/// <exception cref="ArgumentOutOfRangeException">
		///		<paramref name="index"/> is outside the range of valid indices for the <see cref="DbConnectionProviders"/>.
		///	</exception>
		/// <exception cref="NotSupportedException">
		///		<para>The <see cref="DbConnectionProviders"/> is read-only.</para>
		///		<para>-or-</para>
		///		<para>The <b>DbConnectionProviders</b> has a fixed size.</para>
		/// </exception>
		/// <remarks>
		///		<para>The index sequence is based on the sort sequence. When an element is added, 
		///		it is inserted into <see cref="DbConnectionProviders"/> in the correct sort order, and 
		///		the indexing adjusts accordingly. When an element removed, the indexing also adjusts 
		///		accordingly. Therefore, the index of a specific key-and-value pair might change as 
		///		elements are added or removed from the <see cref="DbConnectionProviders"/>.</para>
		///		<para>In collections of contiguous elements, such as lists, the elements that
		///		follow the removed element move up to occupy the vacated spot. If the collection is
		///		indexed, the indices of the elements that are moved are also updated.</para>
		/// </remarks>
		public virtual void RemoveAt(int index) {
			if (index < 0 || index >= count)
				throw new ArgumentOutOfRangeException("index", index, "The index is outside the range of valid indices.");

			count--;
			if (index < count) {
				Array.Copy(keys, index + 1, keys, index, count - index);
				Array.Copy(values, index + 1, values, index, count - index);
			}

			// We can't set the deleted entries equal to null, because they might be value types.
			// Instead, we'll create empty single-element arrays of the right type and copy them 
			// over the entries we want to erase.
			string[] tempKey = new string[1];
			DbConnectionProvider[] tempVal = new DbConnectionProvider[1];
			Array.Copy(tempKey, 0, keys, count, 1);
			Array.Copy(tempVal, 0, values, count, 1);

			version++;
		}
		/// <summary>
		///		Replaces the value at a specific index in the <b>DbConnectionProviders</b>.
		/// </summary>
		/// <param name="index">The zero-based index at which to save <paramref name="value"/>.</param>
		/// <param name="value">The <see cref="DbConnectionProvider"/> to save into the <see cref="DbConnectionProviders"/>.</param>
		/// <exception cref="ArgumentOutOfRangeException">
		///		<paramref name="index"/> is outside the range of valid indices for the <see cref="DbConnectionProviders"/>.
		/// </exception>
		/// <remarks>
		///		<para>The index sequence is based on the sort sequence. When an element is added, 
		///		it is inserted into <see cref="DbConnectionProviders"/> in the correct sort order, and 
		///		the indexing adjusts accordingly. When an element removed, the indexing also adjusts 
		///		accordingly. Therefore, the index of a specific key-and-value pair might change as 
		///		elements are added or removed from the <see cref="DbConnectionProviders"/>.</para>
		/// </remarks>
		public virtual void SetByIndex(int index, DbConnectionProvider value) {
			if (index < 0 || index >= count)
				throw new ArgumentOutOfRangeException("index", index, "The index is outside the range of valid indices.");

			values[index] = value;
			version++;
		}
		/// <summary>
		///		Determines whether the <b>DbConnectionProviders</b> contains a specific value.
		/// </summary>
		/// <param name="value">The value to locate in the <see cref="DbConnectionProviders"/>.</param>
		/// <returns>
		///		<b>true</b> if the <see cref="DbConnectionProviders"/> contains an element with the specified 
		///		<paramref name="value"/>; otherwise, <b>false</b>.
		/// </returns>
		public virtual bool ContainsValue(DbConnectionProvider value) {
			return (IndexOfValue(value) >= 0);
		}
		/// <summary>
		///		Returns the zero-based index of the first occurrence of the specified value in
		///		the <b>DbConnectionProviders</b>.
		/// </summary>
		/// <param name="value">The value to locate in the <see cref="DbConnectionProviders"/>.</param>
		/// <returns>
		///		The zero-based index of <paramref name="value"/>, if <paramref name="value"/> is found in
		///		the <see cref="DbConnectionProviders"/>; otherwise, -1.
		/// </returns>
		/// <remarks>
		///		<para>The index sequence is based on the sort sequence. When an element is added, 
		///		it is inserted into <see cref="DbConnectionProviders"/> in the correct sort order, and 
		///		the indexing adjusts accordingly. When an element removed, the indexing also adjusts 
		///		accordingly. Therefore, the index of a specific key-and-value pair might change as 
		///		elements are added or removed from the <see cref="DbConnectionProviders"/>.</para>
		///		<para>The values of the elements of the <see cref="DbConnectionProviders"/> are compared to the 
		///		specified value using the Equals method.</para>
		///		<para>This method uses a linear search; therefore, the average execution time is 
		///		proportional to <see cref="DbConnectionProviders.Count"/>.</para>
		/// </remarks>
		public virtual int IndexOfValue(DbConnectionProvider value) {
			return Array.IndexOf(values, value, 0, count);
		}
		/// <summary>
		///		Adds an element with the specified key and value to the <b>DbConnectionProviders</b>.
		/// </summary>
		/// <param name="key">The key of the element to add.</param>
		/// <param name="value">The value of the element to add.</param>
		/// <exception cref="ArgumentNullException">The <paramref name="key"/> is a null reference.</exception>
		/// <exception cref="ArgumentException">
		///		<para>An element with the specified <paramref name="key"/> already exists in the <see cref="DbConnectionProviders"/>.</para>
		///		<para>-or-</para>
		///		<para>The <b>DbConnectionProviders</b> is set to use the <see cref="IComparable"/> interface,
		///		and <paramref name="key"/> does not implement the <b>IComparable</b> interface.</para>
		/// </exception>
		/// <exception cref="InvalidOperationException">The comparer throws an exception.</exception>
		/// <exception cref="NotSupportedException">
		///		<para>The <see cref="DbConnectionProviders"/> is read-only.</para>
		///		<para>-or-</para>
		///		<para>The <b>DbConnectionProviders</b> has a fixed size.</para>
		/// </exception>
		public virtual void Add(string key, DbConnectionProvider value) {
			if (Object.ReferenceEquals(key, null)) // avoids compiler error for null check on value type
				throw new ArgumentNullException("key", "The key cannot be null.");

			int index = Array.BinarySearch(keys, 0, count, key, comparer);

			if (index >= 0)
				throw new ArgumentException(String.Format("Item has already been added.  Key being added: \"{0}\".", key));
 
			Insert(~index, key, value);
		}
		public virtual void Add(DbConnectionProvider value) {
			if (Object.ReferenceEquals(value, null))
				throw new ArgumentNullException("value", "The value cannot be null.");

			this.Add(value.Name, value);
		}
			public virtual int IndexOf(DbConnectionProvider value) {
				return list.IndexOfValue(value);
			}
			public virtual bool Contains(DbConnectionProvider value) {
				return list.ContainsValue(value);
			}
			public virtual void Reset() {
				if (version != list.version)
					throw new InvalidOperationException("The collection was modified - enumeration cannot continue.");

				// We can't set the entries equal to null, because they might be value types.
				// Instead, we'll create empty single-element arrays of the right type and copy them 
				// over the entries we want to erase.
				string[] tempKey = new string[1];
				DbConnectionProvider[] tempVal = new DbConnectionProvider[1];
				key = tempKey[0];
				value = tempVal[0];
				currentValid = false;
				index = startIndex;
			}
			public override void SetByIndex(int index, DbConnectionProvider value) {
				lock (root)
					list.SetByIndex(index, value);
			}
			public override int IndexOfValue(DbConnectionProvider value) {
				lock (root)
					return list.IndexOfValue(value);
			}