Ninja Database Pro
Creating Custom Indexes

It is possible to create custom indexes based on either BaseSingleIndex or BaseCompositeIndex.  Below is the source code of the Single Index as an example.

 

/// <summary>

/// An index used for a single type.

/// </summary>

/// <typeparam name="T"></typeparam>

/// <typeparam name="TIndex"></typeparam>

public class SingleIndex<T, TIndex> : BaseSingleIndex<T,TIndex> where T : class, new()

{

#region Variables

protected Dictionary<TIndex, SingleIndexRecord<T, TIndex>> UniqueItems = new Dictionary<TIndex, SingleIndexRecord<T, TIndex>>();

protected List<SingleIndexRecord<T, TIndex>> NonUniqueItems = new List<SingleIndexRecord<T, TIndex>>();

#endregion

 

#region Properties

/// <summary>

/// Used for serialization and deserialization. A dictionary with the primary key for the key, and the index for the value

/// </summary>

public override Dictionary<long, TIndex> SerializedDictionary

{

get { return NonUniqueItems.ToDictionary(item => item.PrimaryKey, item => item.Index); }

set

{

NonUniqueItems = new List<SingleIndexRecord<T, TIndex>>(value.Count);

if (Style == IndexStyle.Unique)

{

UniqueItems = new Dictionary<TIndex, SingleIndexRecord<T, TIndex>>(value.Count);

}

foreach (SingleIndexRecord<T, TIndex> record in value.Select(item => new SingleIndexRecord<T, TIndex>(this, item.Key, item.Value)))

{

NonUniqueItems.Add(record);

if (Style == IndexStyle.Unique)

{

UniqueItems.Add(record.Index, record);

}

}

}

}

#endregion

#region Methods

/// <summary>

/// Clear all lazy loaded values

/// </summary>

public override void ClearLazyLoadedValues()

{

foreach (var singleIndexRecord in NonUniqueItems)

{

singleIndexRecord.LazyValue = null;

}

}

/// <summary>

/// Clear all the items in the index and set IsDirty to true

/// </summary>

public override void Clear()

{

IsDirty = true;

NeedsSorted = false;

UniqueItems.Clear();

NonUniqueItems.Clear();

}

/// <summary>

/// Insert an index value into the index. It is assumed that it has already been checked for uniqueness

/// </summary>

/// <param name="primaryKey"></param>

/// <param name="indexValue"></param>

public override void Insert(long primaryKey, object indexValue)

{

TIndex valueToInsert = (TIndex)Common.ChangeType(indexValue, typeof(object), typeof(TIndex));

SingleIndexRecord<T, TIndex> indexRecord = new SingleIndexRecord<T, TIndex>(this, primaryKey, valueToInsert);

IsDirty = true;

NeedsSorted = true;

if (Style == IndexStyle.Unique)

{

if (UniqueItems.ContainsKey(valueToInsert))

throw new NinjaDbProException(Common.BuildUniqueIndexViolationMessage(indexValue, primaryKey, ClassName, IndexName));

UniqueItems.Add(valueToInsert, indexRecord);

}

NonUniqueItems.Add(indexRecord);

}

 

/// <summary>

/// Update an index value by the primary key

/// </summary>

/// <param name="primaryKey"></param>

/// <param name="indexValue"></param>

public override void Update(long primaryKey, object indexValue)

{

if (Style == IndexStyle.Unique)

{

UpdateUniqueIndex(primaryKey, indexValue);

}

UpdateIndexRecords(primaryKey, indexValue);

}

private void UpdateUniqueIndex(long primaryKey, object indexValue)

{

TIndex valueToUpdate = (TIndex)Common.ChangeType(indexValue, typeof(object), typeof(TIndex));

if (UniqueItems.ContainsKey(valueToUpdate))

{

//No change

if (UniqueItems[valueToUpdate].PrimaryKey == primaryKey)

return;

 

string msg = Common.BuildUniqueIndexViolationMessage(indexValue.ToString(), primaryKey, ClassName,

IndexName);

throw new NinjaDbProException(msg);

}

bool found = false;

TIndex existingIndexValue = default(TIndex);

//Remove existing item

foreach (var keyValuePair in UniqueItems)

{

if (keyValuePair.Value.PrimaryKey == primaryKey)

{

found = true;

existingIndexValue = keyValuePair.Key;

break;

}

}

 

if (found)

UniqueItems.Remove(existingIndexValue);

 

SingleIndexRecord<T, TIndex> indexRecord = new SingleIndexRecord<T, TIndex>(this, primaryKey, valueToUpdate);

UniqueItems.Add(valueToUpdate, indexRecord);

IsDirty = true;

}

private void UpdateIndexRecords(long primaryKey, object indexValue)

{

TIndex valueToUpdate = (TIndex)Common.ChangeType(indexValue, typeof(object), typeof(TIndex));

SingleIndexRecord<T, TIndex> indexRecord = NonUniqueItems.FirstOrDefault(o => o.PrimaryKey == primaryKey);

if (indexRecord == null)

{

indexRecord = new SingleIndexRecord<T, TIndex>(this, primaryKey, valueToUpdate);

NonUniqueItems.Add(indexRecord);

IsDirty = true;

NeedsSorted = true;

}

else

{

if (!Common.Compare(indexRecord.Index, valueToUpdate))

{

IsDirty = true;

NeedsSorted = true;

indexRecord.Index = valueToUpdate;

indexRecord.LazyValue = null;

}

}

}

/// <summary>

/// Delete an item in the index by primary key and set IsDirty to true

/// </summary>

/// <param name="primaryKey"></param>

public override void Delete(long primaryKey)

{

if (Style == IndexStyle.Unique)

{

if (UniqueItems.Any(o => o.Value.PrimaryKey == primaryKey))

{

TIndex indexValue = UniqueItems.First(o => o.Value.PrimaryKey == primaryKey).Key;

UniqueItems.Remove(indexValue);

IsDirty = true;

}

}

var indexRecord = NonUniqueItems.FirstOrDefault(o => o.PrimaryKey == primaryKey);

if (indexRecord != null)

{

NonUniqueItems.Remove(indexRecord);

IsDirty = true;

NeedsSorted = true;

}

}

/// <summary>

/// Get all the primary keys associated with this index in ascending order

/// </summary>

/// <returns></returns>

public override List<long> GetPrimaryKeys(object indexValue)

{

TIndex indexToFind = (TIndex)Common.ChangeType(indexValue, typeof(object), typeof(TIndex));

List<long> primaryKeys = (from nonUniqueItem in NonUniqueItems

where Common.Compare(nonUniqueItem.Index, indexToFind)

select nonUniqueItem.PrimaryKey).ToList();

return primaryKeys;

}

/// <summary>

/// Get all the primary keys associated with this index in descending order

/// </summary>

/// <returns></returns>

public override List<long> GetAllPrimaryKeysDescending()

{

var sortedDescending = NonUniqueItems.OrderByDescending(o => o.Index);

return sortedDescending.Select(indexRecord => indexRecord.PrimaryKey).ToList();

}

/// <summary>

/// Get all the primary keys associated with this index

/// </summary>

/// <returns></returns>

public override List<long> GetAllPrimaryKeys()

{

if (NeedsSorted)

{

SortIndex();

NeedsSorted = false;

}

return NonUniqueItems.Select(indexRecord => indexRecord.PrimaryKey).ToList();

}

/// <summary>

/// Sort the index by the index value

/// </summary>

public override void SortIndex()

{

NonUniqueItems = NonUniqueItems.OrderBy(o => o.Index).ToList();

}

/// <summary>

/// Query for a list of index records

/// </summary>

/// <returns></returns>

public override List<SingleIndexRecord<T, TIndex>> Query()

{

return NonUniqueItems;

}

/// <summary>

/// Get a list of Index Records that match the passed indexValue

/// </summary>

/// <param name="indexValue"></param>

/// <returns></returns>

public override List<SingleIndexRecord<T, TIndex>> GetIndexRecordExactMatch(TIndex indexValue)

{

List<SingleIndexRecord<T, TIndex>> result = new List<SingleIndexRecord<T, TIndex>>();

if (Style == IndexStyle.Unique)

{

if (UniqueItems.ContainsKey(indexValue))

{

result.Add(UniqueItems[indexValue]);

}

}

else

{

result.AddRange(NonUniqueItems.Where(o => Common.Compare(o.Index, indexValue)));

}

return result;

}

#endregion

}