Skip to content

Entity Aliases

David West edited this page Aug 26, 2016 · 24 revisions

< Entity Definitions

The Concept

The concept of an alias as it pertains to a tree node is strongly related to the notion of the core entity's name. Compared to an entity's actual id which should be globally unique to the entity tree, an entity's alias would be a property or set of properties that could distinguish it uniquely among its siblings in the tree, usually in a human-readable sense. This is motivated by, among other things, a fairly common requirement that a node's name path be unique.

For example:

Suppose there are two distinct entities (with ids 52 and 111) that have the same name but are not siblings in a hierarchy. Their name paths may look something like this:

  • Catalog / Sporting Goods / Fishing / Boots (52)
  • Catalog / Apparel / Women / Footwear / Boots (111)

This re-use of names seems reasonable; uniqueness is achieved through the signature of the entire path. Now suppose there are two distinct entities (with ids 206 and 19) that have the same name and are siblings in a hierarchy:

  • Catalog / Electronics / TVs / Smart TVs (206)
  • Catalog / Electronics / TVs / Smart TVs (19)

Obviously, ambiguity and confusion would ensue. If we hoped to make a natural URL out of these name paths, we could not because they clearly don't appear to be unique resources. Nor would this kind of duplication be tolerated in a file system.

Applying This

Getting back to the IEntityDefinition<TId, TItem> interface, the AliasEqualityComparer property instructs the host tree how to compare entities on the basis of their alias.

Going back to our example, let's see how we could create an entity definition that assumes Category.Name to be the sole property that carries the entity alias and that equality tests of these values should be case insensitive. One approach would be to create a custom comparer class. Instead, let's jump to an easier solution by introducing a slightly more evolved interface:

public interface IEntityDefinition<TId, out TName, in TItem> 
       : IEntityDefinition<TId, TItem>
{
    Func<TItem, TName> GetName { get; } 
}

As you can see, this assumes that an entity alias is simply one property (of type TName) which names the entity; thus, the GetName property of this interface is a function that knows how to aquire this property from an entity of type TItem. Along with this, we can use the concrete class EntityDefinition<TId, TName, TItem> (which derives from the less-specific EntityDefinition<TId, TItem> class and implements IEntityDefinition<TId, TName, TItem>) to achieve our goal:

var def = new EntityDefinition<int, string, Category>(c => c.CategoryId,
                                                      c => c.Name, 
                                                      EqualityComparer<int>.Default, 
                                                      StringComparer.OrdinalIgnoreCase);

var root = new ReadOnlyEntityTreeNode<int, Category>(def, rootItem);

The second parameter of the definition constructor is the function that states how to access the entity name. The last parameter allows us to specify how the type TName (in this case string) should be compared for equality. Internally, an alias comparer of type IEqualityComparer<TItem> is being made for us (in this case IEqualityComparer<Category>), so we don't have to go through the hassle of coding this custom comparer class.

There are cases when an entity alias may go beyond just being a single name property, but this will be discussed in a later section.

Note that if an entity does not naturally have the concept of an alias, all of this is a non-issue; the alias comparer is an optional parameter in the EntityDefinition<TId, TItem> constructor. In the case where it were not supplied, the AliasEqualityComparer property would simply become the default equality comparer for the type TItem (which will most likely be an object reference comparison unless TItem overrides the Equals method).

Now that we understanding about entity definitions and entity aliases, let's turn our attention to referential error detection.

Error Detection >

Clone this wiki locally