Inheritance: BaseMetadata
 public static string AppendSelectListAndGetFirstColumnFor(
     StringBuilder buffer,
     DtoMetadata metadata,
     string tableAlias = null)
 {
     return AppendSelectListAndGetFirstColumnFor(buffer, metadata, false, tableAlias);
 }
 public static string BuildSelectListFor(
     DtoMetadata metadata,
     string tableAlias = null)
 {
     var buffer = new StringBuilder();
     AppendSelectListAndGetFirstColumnFor(buffer, metadata, tableAlias);
     return buffer.ToString();
 }
        public DtoMetadata GetMetadataFor(Type type)
        {
            if (type == typeof(string))
            {
                throw new ArgumentException(
                          "DtoMetadata retrieval is not supported for strings.",
                          "type");
            }

            lock (_lock)
            {
                DtoMetadata data;
                _metadata.TryGetValue(type, out data);
                if (null == data)
                {
                    data = new DtoMetadata(type);
                    _metadata.Add(type, data);
                }
                return(data);
            }
        }
        private void AppendJoin(
            TypePropertyMap map,
            int index,
            TypePropertyMapEntry entry,
            string aliasForCurrentTable,
            StringBuilder fromAndJoinsBuff,
            DtoMetadata metadata,
            string [] aliases)
        {
            var target = map.GetEntryWithMatchingPropertyPreceding(index, entry.Type);
            if (target == null)
            {
                throw new InvalidOperationException(
                    string.Format(
                        "Unable to find any property "
                        + "that fits type '{0}'. Please ensure you have included all the necessary "
                        + "types in your query, and that any type to which '{0}' should be added "
                        + "precedes it in the list of types otherwise, like soldiers killed in "
                        + "Stanley Kubrick's Full Metal Jacket, you will be in a world of s***.",
                        entry.Type));
            }

            fromAndJoinsBuff.Append("LEFT OUTER JOIN ");

            var targetProperty = target.GetPropertyMetadataFor(entry.Type);

            if (targetProperty.HasAttribute<ManyToManyAttribute>())
            {
                var manyToMany = targetProperty.GetAttribute<ManyToManyAttribute>();
                var linkAlias = AppendTableNameAndAlias(fromAndJoinsBuff, manyToMany.SchemaQualifiedLinkTableName);

                fromAndJoinsBuff.Append("    ON ");
                AppendJoinConditionArgument(target, fromAndJoinsBuff, target.Metadata.PrimaryKey, aliases);
                fromAndJoinsBuff.Append(" = ");
                AppendJoinConditionArgument(fromAndJoinsBuff, target.Metadata.PrimaryKey, linkAlias);

                fromAndJoinsBuff.Append(Environment.NewLine);

                fromAndJoinsBuff.Append("LEFT OUTER JOIN ");

                var table = metadata.GetAttribute<TableAttribute>();
                AppendTableNameAndAlias(fromAndJoinsBuff, table, aliasForCurrentTable);

                fromAndJoinsBuff.Append("    ON ");
                AppendJoinConditionArgument(entry, fromAndJoinsBuff, metadata.PrimaryKey, aliases);
                fromAndJoinsBuff.Append(" = ");
                AppendJoinConditionArgument(fromAndJoinsBuff, metadata.PrimaryKey, linkAlias);

                fromAndJoinsBuff.Append(Environment.NewLine);
            }
            else
            {
                var table = metadata.GetAttribute<TableAttribute>();

                AppendTableNameAndAlias(fromAndJoinsBuff, table, aliasForCurrentTable);

                fromAndJoinsBuff.Append("    ON ");
                if (targetProperty.HasAttribute<OneToOneAttribute>() && string.IsNullOrEmpty(targetProperty.GetAttribute<OneToOneAttribute>().ChildForeignKeyColumn))
                {
                    //  Covers situation where foreign key column is on the target table
                    AppendJoinConditionArgument(entry, fromAndJoinsBuff, metadata.PrimaryKey, aliases);
                    fromAndJoinsBuff.Append(" = ");
                    AppendJoinConditionArgument(target, fromAndJoinsBuff, targetProperty, aliases);
                }
                else if (targetProperty.HasAttribute<ManyToOneAttribute>())
                {
                    var manyToOne = targetProperty.GetAttribute<ManyToOneAttribute>();
                    var targetColumn = manyToOne.ForeignKeyTargetColumnName;
                    if (string.IsNullOrEmpty(targetColumn))
                    {
                        AppendJoinConditionArgument(entry, fromAndJoinsBuff, metadata.PrimaryKey, aliases);
                    }
                    else
                    {
                        AppendJoinConditionArgument(entry, fromAndJoinsBuff, targetColumn, aliases);
                    }

                    fromAndJoinsBuff.Append(" = ");
                    AppendJoinConditionArgument(target, fromAndJoinsBuff, targetProperty, aliases);
                }
                else if (targetProperty.HasAttribute<OneToOneAttribute>() || targetProperty.HasAttribute<OneToManyAttribute>())
                {
                    //  Covers situation where foreign key column is on the source table
                    AppendJoinConditionArgument(entry, fromAndJoinsBuff, entry.GetPropertyMetadataFor(target.Type), aliases);
                    fromAndJoinsBuff.Append(" = ");
                    AppendJoinConditionArgument(target, fromAndJoinsBuff, target.Metadata.PrimaryKey, aliases);
                }
                else
                {
                    throw new InvalidOperationException(
                        string.Format(
                            "Unable to generate JOIN condition between types '{0}' and '{1}' because the property '{2}' on '{1}' "
                            + "is not decorated with an attribute indicating its cardinality. Please add a [OneToOne], [OneToMany] "
                            + "[ManyToOne], or [ManyToMany] decoration, as appropriate.",
                            metadata.DtoType,
                            target.Type,
                            targetProperty.Prop.Name));
                }

                fromAndJoinsBuff.Append(Environment.NewLine);
            }
        }
        public static string AppendSelectListAndGetFirstColumnFor(
            StringBuilder buffer,
            DtoMetadata metadata,
            bool iNeedALeadingComma,
            string tableAlias = null)
        {
            string firstColumn = null;
            foreach (var property in metadata.AllProperties)
            {
                //  At the moment this isn't sophisticated enough to drill down through tables.
                //  We might want to add this in future but, given it's currently only used to retrieve
                //  data to populate lists and dropdowns it seems unnecessary.
                if (!property.Prop.CanWrite
                    || property.HasAttribute<OneToManyAttribute>()
                    || property.HasAttribute<ManyToManyAttribute>()
                    || property.HasAttribute<ManyToOneAttribute>()
                    || property.HasAttribute<OneToOneAttribute>()
                    || property.HasAttribute<SimpleLoadIgnoreAttribute>()
                    || property.IsEnumerable)
                {
                    continue;
                }

                //if (property.HasAttribute<OneToOneAttribute>()
                //    && !string.IsNullOrEmpty(property.GetAttribute<OneToOneAttribute>().ChildForeignKeyColumn))
                //{
                //    continue;
                //}

                if (buffer.Length > 0 || iNeedALeadingComma)
                {
                    buffer.Append(", ");
                    buffer.Append(Environment.NewLine);
                    buffer.Append("    ");
                }

                if (!string.IsNullOrEmpty(tableAlias))
                {
                    buffer.Append('[');
                    buffer.Append(tableAlias);
                    buffer.Append("].");
                }

                buffer.Append('[');
                buffer.Append(property.ColumnName);
                buffer.Append(']');

                var columnAlias = property.ColumnName;

                if (columnAlias != property.Prop.Name
                    && ! property.HasAttribute<ManyToOneAttribute>()
                    && ! property.HasAttribute<OneToOneAttribute>())
                {
                    columnAlias = property.Prop.Name;
                    buffer.Append(" AS [");
                    buffer.Append(columnAlias);
                    buffer.Append("]");
                }

                if (firstColumn == null)
                {
                    firstColumn = columnAlias;
                }
            }
            return firstColumn;
        }