void IMapping.InnerApply(MappingContext c)
        {
            var context = (MappingContext <T>)c;

            // .......................
            // GET ALL MAPPINGS

            List <IMapping> mappingsToApply = null;

            foreach (IMapping mapping in ((IMapping)this).GetAllMappings(includeBase: true))
            {
                if (mappingsToApply == null)
                {
                    mappingsToApply = new List <IMapping>();
                }

                mappingsToApply.Add(mapping);
            }

            // .......................
            // APPLY CHILD MAPPINGS

            Dictionary <IEntityProperty, object> propertyValues = null;
            bool hasChildMappings = false;

            // Apply current mappings
            for (int i = 0; i < mappingsToApply.Count; i++)
            {
                IMapping mapping = mappingsToApply[i];

                // Ignore subquery mappings that aren't the current mapping
                if (mapping is ISubqueryMapping && context.CurrentSubquery.Mapping != mapping)
                {
                    continue;
                }

                MappingContext currentContext = mapping is IChildMapping?
                                                mapping.CreateContext(context) :
                                                    context;

                mapping.Apply(currentContext);
                if (context.DoBreak)
                {
                    break;
                }

                if (mapping is IChildMapping)
                {
                    // If a target has been specified, save it
                    if (currentContext.IsTargetSet)
                    {
                        hasChildMappings = true;

                        if (mapping is IPropertyMapping)
                        {
                            if (propertyValues == null)
                            {
                                propertyValues = new Dictionary <IEntityProperty, object>();
                            }

                            var propertyMapping = (IPropertyMapping)mapping;
                            propertyValues.Add(propertyMapping.Property, currentContext.Target);
                        }
                        else if (mapping is IVariableMapping)
                        {
                            var variableMapping = (IVariableMapping)mapping;
                            context.SetVariable(variableMapping.Variable, currentContext.Target);
                        }
                    }
                }

                // There might be derived mappings at this point, find them
                if (i == mappingsToApply.Count - 1 && context.TargetType != null)
                {
                    IEntityDefinition definition = this.EntitySpace.GetDefinition(context.TargetType);
                    if (definition != null)
                    {
                        // TODO: better way to indicate which derived mapping to use - possibly by name
                        IMapping derived = null;
                        foreach (IMapping d in definition.Mappings.Where(m => m.BaseMapping == this))
                        {
                            derived = d;
                            break;
                        }

                        // Get all inherit
                        if (derived != null)
                        {
                            mappingsToApply.AddRange(derived.GetAllMappings(includeBase: true, untilBase: typeof(T)));
                        }
                    }
                }
            }

            // .......................
            // GET FROM CACHE

            bool isEntity    = this.EntitySpace.GetDefinition <T>() != null;
            bool shouldCache = isEntity && this.CacheIdentity != null && propertyValues != null && this.CacheIdentity.HasValidValues(propertyValues);

            if (shouldCache)
            {
                Identity cacheId = this.CacheIdentity.IdentityFromValues(propertyValues);

                object val = context.Cache.Get <T>(cacheId);
                if (val != null)
                {
                    // Update cache
                    context.Target = (T)val;
                    context.Cache.Update(this.CacheIdentity, propertyValues);
                    shouldCache = false;
                }
            }

            // .......................
            // INSTANTIATION

            // Instantiate target if it hasn't been specifically applied and there are sub mappings that have executed
            if (!context.IsTargetSet && hasChildMappings)
            {
                // Instantiate a new target
                context.Target = context.TargetType != null ?
                                 (T)Activator.CreateInstance(context.TargetType) :
                                 Activator.CreateInstance <T>();
            }

            // .......................
            // PUT IN CACHE

            if (context.IsTargetSet && propertyValues != null)
            {
                // Apply properties
                foreach (var propVal in propertyValues)
                {
                    propVal.Key.SetValue(context.Target, propVal.Value);
                }

                // Add to cache
                if (shouldCache)
                {
                    context.Cache.Put <T>(this.CacheIdentity, context.Target, propertyValues.Keys.ToArray());
                }
            }
        }