|
///////////////////////////////////////////////////////////////////////////
// Copyright 2003-2005 Falcon Soon
//
// Author: Soon Chun Boon
// Date: 21 September 2004
// Description:
// Class that represents primary keys or foreign keys in data relationship.
///////////////////////////////////////////////////////////////////////////
using System;
using System.Data;
namespace DBHelper
{
/// <summary>
/// Class that represents primary keys or foreign keys.
/// </summary>
internal class DBKey
{
#region Class Member Declarations
internal const int COLUMN = 65535;
internal const int DESCENDING = -2147483648;
internal const int MAX_COLUMNS = 32;
internal DataColumn[] macolKey;
internal bool mbExplicitKey;
internal int miSortOrder;
#endregion
/// <summary>
/// Initialize a new instance of <see cref="DBHelper.DBKey"/> class with the specified
/// data columns.
/// </summary>
/// <param name="acol">An array of <see cref="System.Data.DataColumn"/> which forms
/// the database key.</param>
/// <exception cref="System.ArgumentNullException">
/// Bad data columns are passed.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyNoColumns">
/// Zero data column is passed.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyTooManyColumns">
/// Total of passed in data columns is more than the maximum.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyDuplicateColumns">
/// Duplicate data columns is passed.
/// </exception>
/// <exception cref="DBHelper.DataException.KeySortLength">
/// Passed in sort order total is not same as data column total.
/// </exception>
/// <exception cref="DBHelper.DataException.ColumnNotInAnyTable">
/// A <see cref="System.Data.DataColumn"/> is not belonging to any
/// <see cref="System.Data.DataTable"/>.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyTableMismatch">
/// <see cref="System.Data.DataTable"/> for every <see cref="System.Data.DataColumn"/>
/// is not same.
/// </exception>
public DBKey(DataColumn[] acol)
{
this.Create(acol, null);
}
/// <summary>
/// Check whether every column in key belong to same table.
/// </summary>
/// <exception cref="DBHelper.DataException.ColumnNotInAnyTable">
/// A <see cref="System.Data.DataColumn"/> is not belonging to any
/// <see cref="System.Data.DataTable"/>.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyTableMismatch">
/// <see cref="System.Data.DataTable"/> for every <see cref="System.Data.DataColumn"/>
/// is not same.
/// </exception>
internal void CheckState()
{
DataTable tblKey = this.macolKey[0].Table;
if (tblKey == null)
{
throw new DataException.ColumnNotInAnyTable();
}
for (int iIndex = 1; (iIndex < this.macolKey.Length); iIndex++)
{
if (this.macolKey[iIndex].Table == null)
{
throw new DataException.ColumnNotInAnyTable();
}
if (this.macolKey[iIndex].Table != tblKey)
{
throw new DataException.KeyTableMismatch();
}
}
}
/// <summary>
/// Create a new database key.
/// </summary>
/// <param name="acol">An array of <see cref="System.Data.DataColumn"/> which
/// represent the database key.</param>
/// <param name="aiSortOrders">An array of integer which represent each column's
/// sort order.</param>
/// <exception cref="System.ArgumentNullException">
/// Bad data columns are passed.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyNoColumns">
/// Zero data column is passed.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyTooManyColumns">
/// Total of passed in data columns is more than the maximum.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyDuplicateColumns">
/// Duplicate data columns is passed.
/// </exception>
/// <exception cref="DBHelper.DataException.KeySortLength">
/// Passed in sort order total is not same as data column total.
/// </exception>
/// <exception cref="DBHelper.DataException.ColumnNotInAnyTable">
/// A <see cref="System.Data.DataColumn"/> is not belonging to any
/// <see cref="System.Data.DataTable"/>.
/// </exception>
/// <exception cref="DBHelper.DataException.KeyTableMismatch">
/// <see cref="System.Data.DataTable"/> for every <see cref="System.Data.DataColumn"/>
/// is not same.
/// </exception>
private void Create(DataColumn[] acol, int[] aiSortOrders)
{
this.mbExplicitKey = false;
if (acol == null)
{
throw new ArgumentNullException("acol");
}
if (acol.Length == 0)
{
throw new DataException.KeyNoColumns();
}
if (acol.Length > MAX_COLUMNS)
{
throw new DataException.KeyTooManyColumns(MAX_COLUMNS);
}
for (int iIndex = 0; (iIndex < acol.Length); iIndex++)
{
if (acol[iIndex] == null)
{
throw new ArgumentNullException("acol");
}
}
for (int iIndex = 0; (iIndex < acol.Length); iIndex++)
{
for (int iIndex2 = 0; (iIndex2 < iIndex); iIndex2++)
{
if (acol[iIndex] == acol[iIndex2])
{
throw new DataException.KeyDuplicateColumns(acol[iIndex].ColumnName);
}
}
}
if ((aiSortOrders != null) && (aiSortOrders.Length != acol.Length))
{
throw new DataException.KeySortLength();
}
this.miSortOrder = 0;
if (aiSortOrders != null)
{
for (int iIndex = 0; (iIndex < aiSortOrders.Length); iIndex++)
{
this.miSortOrder |= ((aiSortOrders[iIndex] & 1) << (iIndex & 31));
}
}
this.macolKey = new DataColumn[acol.Length];
for (int iIndex = 0; (iIndex < acol.Length); iIndex++)
{
this.macolKey[iIndex] = acol[iIndex];
}
this.CheckState();
}
#region Equality and Hash Code Methods
/// <summary>
/// Compare the equality of the specified DBKey instance with this DBKey instance.
/// </summary>
/// <param name="objKey">The DBKey instance to compare.</param>
/// <returns>True if the compared DBKey instance is equal with this DBKey instance,
/// otherwise return False.</returns>
public virtual bool ColumnsEqual(DBKey objKey)
{
int iIndexMain;
int iIndexCompare;
DataColumn[] acolMainKey = this.Columns;
DataColumn[] acolCompareKey = objKey.Columns;
if (acolMainKey == acolCompareKey)
{
return (true);
}
if ((acolMainKey == null) || (acolCompareKey == null))
{
return (false);
}
if (acolMainKey.Length != acolCompareKey.Length)
{
return (false);
}
for (iIndexMain = 0; (iIndexMain < acolMainKey.Length); iIndexMain++)
{
iIndexCompare = 0;
while ((iIndexCompare < acolCompareKey.Length))
{
if (acolMainKey[iIndexMain].Equals(acolCompareKey[iIndexCompare]))
{
break;
}
++iIndexCompare;
}
if (iIndexCompare == acolCompareKey.Length)
{
return (false);
}
}
return (true);
}
/// <summary>
/// Checks whether the specified DataColumn instance is in the database key.
/// </summary>
/// <param name="col">The DataColumn instance to be checked.</param>
/// <returns>True if the DataColumn instance is in the key otherwise return False.</returns>
public virtual bool ContainsColumn(DataColumn col)
{
for (int iIndex = 0; (iIndex < this.macolKey.Length); iIndex++)
{
if (col == this.macolKey[iIndex])
{
return (true);
}
}
return (false);
}
/// <summary>
/// Checks the equality of the compared <see cref="DBHelper.DBKey"/> instance
/// with this <see cref="DBHelper.DBKey"/> instance.
/// </summary>
/// <param name="objCompareKey">The <see cref="DBHelper.DBKey"/> instance to be compared.</param>
/// <returns>True if the compared <see cref="DBHelper.DBKey"/> instance is same with this
/// <see cref="DBHelper.DBKey"/> instance otherwise return False.</returns>
public override bool Equals(object objCompareKey)
{
if (!(objCompareKey is DBKey))
{
return (false);
}
bool bFlag = false;
DataColumn[] acolMain = this.Columns;
DataColumn[] acolCompare = ((DBKey) objCompareKey).Columns;
if (acolMain == acolCompare)
{
return (true);
}
if ((acolMain == null) || (acolCompare == null))
{
return (false);
}
if (acolMain.Length != acolCompare.Length)
{
return (false);
}
bFlag = true;
for (int iIndex = 0; (iIndex < acolMain.Length); iIndex++)
{
if (!acolMain[iIndex].Equals(acolCompare[iIndex]))
{
return (false);
}
}
return (bFlag);
}
/// <summary>
/// Gets the debug string of this <see cref="DBHelper.DBKey"/> instance.
/// </summary>
/// <returns>Return a string consists of every key's column with its sort order.</returns>
public string GetDebugString()
{
int[] aiSortOrder = this.SortOrder;
string strText = "{key: ";
for (int iIndex = 0; (iIndex < this.macolKey.Length); iIndex++)
{
strText = strText + this.macolKey[iIndex].ColumnName + ((aiSortOrder[iIndex] == 1) ? " DESC" : "") + ((iIndex < (this.macolKey.Length - 1)) ? ", " : string.Empty);
}
return strText + "}";
}
/// <summary>
/// Gets the hash code of this <see cref="DBHelper.DBKey"/> instance.
/// </summary>
/// <returns>The hash code of this DBKey instance.</returns>
public override int GetHashCode()
{
int iHashCode = 0;
DataColumn[] acol = this.Columns;
if (acol == null)
{
return (iHashCode);
}
int iHashLength = ((acol.Length <= 2) ? acol.Length : 2);
for (int iIndex = 0; (iIndex < iHashLength); iIndex++)
{
iHashCode += acol[iIndex].GetHashCode();
}
return (iHashCode);
}
#endregion
// /// <summary>
// /// Return the index description in an array of integer.
// /// </summary>
// /// <returns>The index description in an array of integer.</returns>
// internal virtual int[] GetIndexDesc()
// {
// int[] aiIndex = new int[this.macolKey.Length];
// int iSortOrder = this.miSortOrder;
// for (int iIndex = 0; (iIndex < this.macolKey.Length); iIndex++)
// {
// aiIndex[iIndex] = (this.macolKey[iIndex].Ordinal | (iSortOrder << 31));
// iSortOrder = (iSortOrder >> 1);
// }
// return (aiIndex);
// }
// internal virtual Index GetSortIndex()
// {
// return (this.GetSortIndex(DataViewRowState.CurrentRows));
// }
// internal virtual Index GetSortIndex(DataViewRowState enuRecordStates)
// {
// return (this.macolKey[0].Table.GetIndex(this.GetIndexDesc(), enuRecordStates, null));
// }
// public virtual bool RecordsEqual(int iRecord1, int iRecord2)
// {
// for (int iIndex = 0; (iIndex < this.macolKey.Length); iIndex++)
// {
// if (this.macolKey[iIndex].Compare(iRecord1, iRecord2) != 0)
// {
// return (false);
// }
// }
// return (true);
// }
// internal static bool SortDecending(int iIndexDesc)
// {
// return ((iIndexDesc & -2147483648) != 0);
// }
// internal static int ColumnOrder(int iIndexDesc)
// {
// return (iIndexDesc & 65535);
// }
#region Class Property Declarations
/// <summary>
/// Returns an array of <see cref="System.Data.DataColumn"/> that forms
/// the database keys.
/// </summary>
public virtual DataColumn[] Columns
{
get
{
return this.macolKey;
}
}
/// <summary>
/// Return an array of integer which specifies the sort order for every data column.
/// </summary>
/// <remarks>
/// 1 is descending otherwise 0 is ascending.
/// </remarks>
public virtual int[] SortOrder
{
get
{
int iSortOrder = this.miSortOrder;
int[] aiSortOrder = new int[this.macolKey.Length];
for (int iIndex = 0; (iIndex < this.macolKey.Length); iIndex++)
{
aiSortOrder[iIndex] = (iSortOrder & 1);
iSortOrder = (iSortOrder >> 1);
}
return (aiSortOrder);
}
}
/// <summary>
/// Return <see cref="System.Data.DataTable"/> of the database keys.
/// </summary>
public virtual DataTable Table
{
get
{
return (this.macolKey[0].Table);
}
}
#endregion
}
}
|
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.
Had worked as analyst programmer for 4 years. Now helping in family business but still involved actively in .Net development whenever there is a free time.