Represents a SQL INSERT command that inserts a single row of data into a table.
Inheritance: BaseInsertDeleteCommand
        private bool AppendInsertCommand(Script script, InsertCommand command, ref int paramIndex)
        {
            bool isPkAssignedByRdbms = true;
            PropertyMetadata guidPKColumn = null;
            var operation = command.Operation;
            if (operation.ValueMetadata != null) {
                if (null != operation.OwnerPropertyMetadata
                    && operation.OwnerPropertyMetadata.HasAttribute<ManyToManyAttribute>()) {
                    //  INSERT record in link table; don't touch either entity table

                    script.Buffer.Append(string.Format(
                        @"INSERT INTO {0} (
    [{1}], [{2}]
) VALUES (
    ",
                        operation.OwnerPropertyMetadata.GetAttribute<ManyToManyAttribute>().SchemaQualifiedLinkTableName,
                        operation.OwnerPrimaryKeyColumn,
                        operation.ValueMetadata.PrimaryKey.Prop.Name));
                        FormatWithParameter(script, @"{0}, {1}
);
",
                            ref paramIndex,
                            new Func<object>(
                                () => operation.OwnerPrimaryKeyAsObject),
                            new Func<object>(
                                () => operation.ValueMetadata.GetPrimaryKeyValueAsObject(operation.Value)));
                    }
                else if (operation.OwnerPropertyMetadata == null
                    || ((operation.OwnerPropertyMetadata.HasAttribute<OneToManyAttribute>()
                        || IsOneToOneRelationshipWithFkOnParent(operation))
                        && !operation.ValueMetadata.HasAttribute<ReferenceDataAttribute>()
                        && !operation.OwnerPropertyMetadata.HasAttribute<ReferenceDataAttribute>())) 
                {
                    //  INSERT the value into the table defined by ValueMetadata
                    
                    var colBuff = new StringBuilder();
                    var valBuff = new StringBuilder();
                    var values = new ArrayList();
                    var index = 0;

                    foreach (var property in operation.ValueMetadata.Properties)
                    {
                        if (property.IsPrimaryKey)
                        {
                            isPkAssignedByRdbms = !property.GetAttribute<PrimaryKeyAttribute>().IsUserAssigned;
                            if (isPkAssignedByRdbms)
                            {
                                var type = property.Prop.PropertyType;
                                if (type != typeof (int)
                                    && type != typeof (int?)
                                    && type != typeof (long)
                                    && type != typeof (long?))
                                {
                                    if (property.Prop.PropertyType == typeof (Guid?)
                                        || property.Prop.PropertyType == typeof (Guid))
                                    {
                                        guidPKColumn = property;
                                    }
                                    else
                                    {
                                        throw new ArgumentException(string.Format(
                                            "Unsupported primary key type {0} on entity {1}. Primary keys must be nullable ints, longs or GUIDs.",
                                            type.FullName,
                                            operation.ValueMetadata.DtoType.FullName));
                                    }
                                }

                                continue;
                            }
                        }

                        var getter = property.Prop.GetGetMethod();

                        if (getter == null
                            || property.HasAttribute<ManyToManyAttribute>()
                            || property.HasAttribute<OneToManyAttribute>()
                            || ! property.IsSaveable)
                        {
                            continue;
                        }

                        AppendPropertyToInsertStatement(
                            colBuff, valBuff, property, ref index, operation, values, getter);
                    }

                    script.Buffer.Append(string.Format(
                    @"INSERT INTO {0} (
    {1}
)",
                        operation.ValueMetadata.TableName,
                        colBuff));

                    if (guidPKColumn != null && isPkAssignedByRdbms)
                    {
                        script.Buffer.Append(string.Format(@"
OUTPUT inserted.[{0}]
",
                            guidPKColumn.ColumnName));
                    }

                    script.Buffer.Append(@" VALUES (
    ");

                    FormatWithParameter(script, valBuff.ToString(), ref paramIndex, values.ToArray());
                    script.Buffer.Append(@"
);
");
                    script.InsertedValue = operation.Value;
                    script.InsertedValueMetadata = operation.ValueMetadata;
                }
            }
            else
            {
                throw new ArgumentException(
                    string.Format(
                        "Invalid INSERT command: {0}",
                        JsonConvert.SerializeObject(command)),
                    "command");
            }

            if (guidPKColumn == null && isPkAssignedByRdbms)
            {
                script.Buffer.Append(@"
SELECT SCOPE_IDENTITY();
");
            }

            return isPkAssignedByRdbms;
        }
        private bool AppendInsertCommand(Script script, InsertCommand command, ref int paramIndex)
        {
            var isPkAssignedByRdbms = true;
            var needsUpdateContingency = false;
            PropertyMetadata guidPKColumn = null;
            var operation = command.Operation;
            if (operation.ValueMetadata != null) {
                if (null != operation.OwnerPropertyMetadata
                    && operation.OwnerPropertyMetadata.HasAttribute<ManyToManyAttribute>())
                {
                    InsertRecordInLinkTable(script, ref paramIndex, operation);
                    script.Buffer.Append(@"
SELECT SCOPE_IDENTITY();
");
                }
                else if (operation.OwnerPropertyMetadata == null
                    || ((operation.OwnerPropertyMetadata.HasAttribute<OneToManyAttribute>()
                        || operation.OwnerPropertyMetadata.HasAttribute<OneToOneAttribute>())//IsOneToOneRelationshipWithFkOnParent(operation)) //  Because 1:1 with FK on child is like 1:N, and we already handle 1:1 with FK on parent anyway
                        && !operation.ValueMetadata.HasAttribute<ReferenceDataAttribute>()
                        && !operation.OwnerPropertyMetadata.HasAttribute<ReferenceDataAttribute>())) 
                {
                    //  INSERT the value into the table defined by ValueMetadata
                    
                    var colBuff = new StringBuilder();
                    var valBuff = new StringBuilder();
                    var values = new ArrayList();
                    var index = 0;

                    var updateCommand = new UpdateCommand();
                    var hasPrimaryKeyValueAlready = false;
                    string pkColumnName = null;

                    var columnsSeenBefore = CreateColumnsSeenBefore();
                    foreach (var property in operation.ValueMetadata.WriteableProperties)
                    {
                        if (property.IsPrimaryKey)
                        {
                            isPkAssignedByRdbms = !property.GetAttribute<PrimaryKeyAttribute>().IsUserAssigned;
                            pkColumnName = property.ColumnName;

                            var pkValue = operation.ValueMetadata.GetPrimaryKeyValueAsObject(operation.Value);
                            if (pkValue != null)
                            {
                                hasPrimaryKeyValueAlready = true;
                            }

                            //updateCommand.AddOperation(new UpdateOperation()
                            //{
                            //    ColumnName = property.ColumnName,
                            //    TableName = operation.ValueMetadata.TableName,
                            //    Value = pkValue,
                            //    ValueMetadata = _dtoMetadataCache.GetMetadataFor(property.Prop.PropertyType),
                            //    Owner = operation.Owner,
                            //    OwnerMetadata = operation.OwnerMetadata,
                            //    OwnerPrimaryKeyColumn = operation.ValueMetadata.PrimaryKey.ColumnName,
                            //    OwnerPropertyMetadata = property
                            //});

                            if (isPkAssignedByRdbms)
                            {
                                var type = property.Prop.PropertyType;
                                if (type != typeof (int)
                                    && type != typeof (int?)
                                    && type != typeof (long)
                                    && type != typeof (long?))
                                {
                                    if (property.Prop.PropertyType == typeof (Guid?)
                                        || property.Prop.PropertyType == typeof (Guid))
                                    {
                                        guidPKColumn = property;
                                    }
                                    else
                                    {
                                        throw new ArgumentException(string.Format(
                                            "Unsupported primary key type {0} on entity {1}. Primary keys must be nullable ints, longs or GUIDs.",
                                            type.FullName,
                                            operation.ValueMetadata.DtoType.FullName));
                                    }
                                }

                                continue;
                            }
                        }

                        var getter = property.Prop.GetGetMethod();

                        if (getter == null
                            || property.HasAttribute<ManyToManyAttribute>()
                            || property.HasAttribute<OneToManyAttribute>()
                            || ! property.IsSaveable)
                        {
                            continue;
                        }

                        //updateCommand.AddOperation(new UpdateOperation()
                        //{
                        //    ColumnName = property.ColumnName,
                        //    TableName = operation.ValueMetadata.TableName,
                        //    Value = operation.Value,
                        //    ValueMetadata = operation.ValueMetadata,
                        //    Owner = operation.Owner,
                        //    OwnerMetadata = operation.OwnerMetadata,
                        //    OwnerPrimaryKeyColumn = operation.OwnerPrimaryKeyColumn,
                        //    OwnerPropertyMetadata = operation.OwnerPropertyMetadata
                        //});

                        CheckAndThrowIfThisColumnHasBeenSeenBefore(
                            columnsSeenBefore, operation.ValueMetadata.TableName, property.ColumnName, command);

                        AppendPropertyToInsertStatement(
                            script, colBuff, valBuff, property, ref index, operation, values, getter, updateCommand);
                    }

                    needsUpdateContingency = !isPkAssignedByRdbms || hasPrimaryKeyValueAlready;

                    if (needsUpdateContingency)
                    {
                        script.Buffer.Append(
                            string.Format(@"IF EXISTS (SELECT * FROM {0} WHERE [{1}] = ",
                            operation.ValueMetadata.TableName,
                            pkColumnName));

                        //  N.B. The PK value doesn't need referencing with a function here because
                        //  we already have a primary key value.
                        FormatWithParameter(
                            script,
                            "{0}",
                            ref paramIndex,
                            null, //  No wire-up required for the IF EXISTS value
                            operation.ValueMetadata.GetPrimaryKeyValueAsObject(operation.Value));

                        script.Buffer.Append(@")
BEGIN
");
                        AppendUpdateCommand(script, updateCommand, ref paramIndex);

                        if (guidPKColumn == null)
                        {
                            script.Buffer.Append(string.Format(@"
SELECT {0};
", operation.ValueMetadata.GetPrimaryKeyValueAsObject(operation.Value)));
                        }
                        else
                        {
                            script.Buffer.Append(string.Format(@"
SELECT '{0}';
", operation.ValueMetadata.GetPrimaryKeyValueAsObject(operation.Value)));
                        }

                        script.Buffer.Append(@"
END
ELSE
BEGIN
");
                    }

                    script.Buffer.Append(string.Format(
                    @"INSERT INTO {0} (
    {1}
)",
                        operation.ValueMetadata.TableName,
                        colBuff));

                    if (guidPKColumn != null && isPkAssignedByRdbms)
                    {
                        script.Buffer.Append(string.Format(@"
OUTPUT inserted.[{0}]
",
                            guidPKColumn.ColumnName));
                    }

                    script.Buffer.Append(@" VALUES (
    ");

                    FormatWithParameter(script, valBuff.ToString(), ref paramIndex, null, values.ToArray());
                    script.Buffer.Append(@"
);
");
                    script.InsertedValue = operation.Value;
                    script.InsertedValueMetadata = operation.ValueMetadata;

                    if (guidPKColumn == null && isPkAssignedByRdbms)
                    {
                        script.Buffer.Append(@"
SELECT SCOPE_IDENTITY();
");
                    }

                    if (needsUpdateContingency)
                    {
                        script.Buffer.Append(@"
END
");
                    }
                }
            }
            else
            {
                throw new ArgumentException(
                    string.Format(
                        "Invalid INSERT command: {0}",
                        JsonConvert.SerializeObject(command)),
                    "command");
            }
            return isPkAssignedByRdbms;
        }