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; }