// TODO: I'm wondering whether to reinstate this check purely for the purpose of validation // and similarly to add one for the situation where the FK column is on the child table. private static bool IsOneToOneRelationshipWithFkOnParent(BaseInsertDeleteOperation operation) { if (operation.OwnerPropertyMetadata.HasAttribute <OneToOneAttribute>() && operation.OwnerPropertyMetadata.HasAttribute <ForeignKeyReferenceAttribute>()) { if (operation.OwnerPropertyMetadata.GetAttribute <ForeignKeyReferenceAttribute>().ReferencedDto == operation.ValueMetadata.DtoType) { return(true); } throw new ArgumentException(string.Format( "Invalid one to one relationship defined between parent {0} and child {1} " + "on property {2} of parent. " + "Parent has one to one relationship with [ForeignKeyReference] attribute " + "but type specified in [ForeignKeyReference] does not match child type. " + "Instead it is {3}. Change the type referenced by [ForeignKeyReference] " + "or change the type of the property to match that specified in " + "[ForeignKeyReference].", operation.OwnerMetadata.DtoType.FullName, operation.ValueMetadata.DtoType.FullName, operation.OwnerPropertyMetadata.Prop.Name, operation.OwnerPropertyMetadata.GetAttribute <ForeignKeyReferenceAttribute>().ReferencedDto.FullName), "operation"); } return(false); }
private static void AddUpdateOnParentTableForInsertDeleteOfOneToOneChildRow(IList <BaseOperation> operations, Difference diff, BaseInsertDeleteOperation insertDeleteOperation) { var updateOperation = new UpdateOperation { OwnerMetadata = insertDeleteOperation.OwnerMetadata, OwnerPropertyMetadata = insertDeleteOperation.OwnerPropertyMetadata, OwnerPrimaryKeyColumn = insertDeleteOperation.OwnerPrimaryKeyColumn, Owner = insertDeleteOperation.Owner, TableName = insertDeleteOperation.OwnerMetadata.TableName, ColumnPropertyMetadata = diff.OwnerPropertyMetadata, ValueMetadata = diff.ValueMetadata, Value = diff.NewValue }; if (insertDeleteOperation is DeleteOperation) { operations.Add(updateOperation); } if (!insertDeleteOperation.ValueMetadata.IsReferenceData && !insertDeleteOperation.OwnerPropertyMetadata.HasAttribute <ReferenceDataAttribute>()) { operations.Add(insertDeleteOperation); } // If it's an INSERT add the update here if (insertDeleteOperation is InsertOperation) { operations.Add(updateOperation); } }
private bool IsViableParentUpdateOnManyToOneRelationship( BaseInsertDeleteOperation insertDeleteOperation, Difference diff) { return(insertDeleteOperation.OwnerMetadata != null && insertDeleteOperation.OwnerPropertyMetadata.IsManyToOneRelationship && diff.OldOwner != null && diff.NewOwner != null); }
private bool IsViableParentUpdateOnOneToOneWithFkInParent( BaseInsertDeleteOperation insertDeleteOperation, Difference diff) { return(insertDeleteOperation.OwnerPropertyMetadata != null && diff.OldOwner != null && diff.NewOwner != null && (insertDeleteOperation.OwnerPropertyMetadata.IsOneToOneRelationship && insertDeleteOperation.OwnerPropertyMetadata.HasAttribute <ForeignKeyReferenceAttribute>())); }
private static void AddUpdateOnParentTableForInsertDeleteOfManyToOneChildRow( IList <BaseOperation> operations, Difference diff, BaseInsertDeleteOperation insertOperation) { var updateOperation = new UpdateOperation { OwnerMetadata = insertOperation.OwnerMetadata, OwnerPropertyMetadata = insertOperation.OwnerPropertyMetadata, OwnerPrimaryKeyColumn = insertOperation.OwnerPrimaryKeyColumn, Owner = insertOperation.Owner, TableName = insertOperation.TableName, ColumnPropertyMetadata = diff.OwnerPropertyMetadata, ValueMetadata = diff.ValueMetadata, Value = diff.NewValue }; operations.Add(updateOperation); }
private bool ShouldFilterOutForParticularCardinalitiesBecauseFkOnParent( BaseInsertDeleteOperation insertDeleteOperation) { if (insertDeleteOperation.OwnerPropertyMetadata != null) { if (insertDeleteOperation.OwnerPropertyMetadata.IsManyToOneRelationship) { return(true); } if (insertDeleteOperation.OwnerPropertyMetadata.IsOneToOneRelationship && insertDeleteOperation.OwnerPropertyMetadata.HasAttribute <ForeignKeyReferenceAttribute>() && (insertDeleteOperation.ValueMetadata.IsReferenceData || insertDeleteOperation.OwnerPropertyMetadata.HasAttribute <ReferenceDataAttribute>()) && !insertDeleteOperation.ValueMetadata.HasUpdateableForeignKeys) { return(true); } } return(false); }
private void ValidateInsertOrDeleteOperation(BaseInsertDeleteOperation insert) { var tableMetadata = insert.ValueMetadata; if (tableMetadata == null) { throw new ArgumentException( "Cannot INSERT or DELETE without metadata for table because we don't know which table we're acting on. " + "BaseInsertDeleteOperation.ValueMetadata must not be null.", "insert"); } // We only need to complain if somebody tries to insert into (or delete from) a top level table at this point. // Insertions into child tables will be transformed into inserts into link tables for many to many // reference data tables later. Deletes for many to many relationships will likewise act against the // link table. if (insert.OwnerMetadata == null && tableMetadata.IsReferenceData) { throw new InvalidOperationException(string.Format( "You cannot INSERT into or DELETE from a reference data table, even if that table contains updateable foreign keys. " + "Invalid table: {0}.", tableMetadata.TableName)); } }
private static void AddUpdateOnParentTableForInsertDeleteOfOneToOneChildRow(IList<BaseOperation> operations, Difference diff, BaseInsertDeleteOperation insertDeleteOperation) { var updateOperation = new UpdateOperation { OwnerMetadata = insertDeleteOperation.OwnerMetadata, OwnerPropertyMetadata = insertDeleteOperation.OwnerPropertyMetadata, OwnerPrimaryKeyColumn = insertDeleteOperation.OwnerPrimaryKeyColumn, Owner = insertDeleteOperation.Owner, TableName = insertDeleteOperation.OwnerMetadata.TableName, ColumnPropertyMetadata = diff.OwnerPropertyMetadata, ValueMetadata = diff.ValueMetadata, Value = diff.NewValue }; if (insertDeleteOperation is DeleteOperation) { operations.Add(updateOperation); } if (!insertDeleteOperation.ValueMetadata.IsReferenceData && !insertDeleteOperation.OwnerPropertyMetadata.HasAttribute<ReferenceDataAttribute>()) { operations.Add(insertDeleteOperation); } // If it's an INSERT add the update here if (insertDeleteOperation is InsertOperation) { operations.Add(updateOperation); } }
private void AppendPropertyToInsertStatement( Script script, StringBuilder colBuff, StringBuilder valBuff, PropertyMetadata property, ref int index, BaseInsertDeleteOperation operation, ArrayList values, MethodInfo getter, UpdateCommand updateCommand) { object columnValueForUpdate = null; if (property.HasAttribute <ForeignKeyReferenceAttribute>() && null != operation.OwnerMetadata && _dtoMetadataCache.GetValidatedMetadataFor( property.GetAttribute <ForeignKeyReferenceAttribute>().ReferencedDto).TableName == operation.OwnerMetadata.TableName) { columnValueForUpdate = new Func <object>(() => operation.OwnerPrimaryKeyAsObject); values.Add(columnValueForUpdate); } else if (property.HasAttribute <ManyToOneAttribute>() && property.GetAttribute <ManyToOneAttribute>().ForeignKeyTargetColumnName != null) { var propValue = property.GetValue(operation.Value); var propTypeMetadata = _dtoMetadataCache.GetValidatedMetadataFor(property.Prop.PropertyType); if (null != propValue && null != propTypeMetadata) { var targetName = property.GetAttribute <ManyToOneAttribute>().ForeignKeyTargetColumnName; var fkTargetProperty = propTypeMetadata[targetName]; if (fkTargetProperty == null) { throw new ArgumentException(string.Format( "Cannot INSERT foreign key value for non existent target column '{0}'" + " specified from column '{1}'.", targetName, property.ColumnName)); } columnValueForUpdate = new Func <object>(() => fkTargetProperty.GetValue(propValue)); values.Add(columnValueForUpdate); } else { columnValueForUpdate = new Func <object>(() => null); values.Add(columnValueForUpdate); } } else if (property.HasAttribute <ManyToOneAttribute>() || property.HasAttribute <OneToOneAttribute>()) { if (property.HasAttribute <OneToOneAttribute>() && !property.HasAttribute <ForeignKeyReferenceAttribute>()) { // One to one relationship where child table references parent rather than the other way around. // This will be saved along with the child object. return; } object propValue = property.GetValue(operation.Value); DtoMetadata propMetadata = _dtoMetadataCache.GetValidatedMetadataFor(property.Prop.PropertyType); columnValueForUpdate = new Func <object>( () => propValue == null || propMetadata == null ? null : propMetadata.GetPrimaryKeyValueAsObject(propValue)); values.Add(columnValueForUpdate); } else { columnValueForUpdate = getter.Invoke(operation.Value, new object[0]); values.Add(columnValueForUpdate); } if (columnValueForUpdate is Func <object> ) { script.WireUpActions.Add(() => { object newPropertyValue = ((Func <object>)columnValueForUpdate)(); if (CanAssignToProperty(newPropertyValue, property)) { property.Prop.SetValue(operation.Value, newPropertyValue); } }); } updateCommand.AddOperation(new UpdateOperation() { ColumnPropertyMetadata = property, TableName = operation.ValueMetadata.TableName, Value = columnValueForUpdate, ValueMetadata = property.IsString || property.IsNumericType || property.IsEnum || !property.IsReferenceType ? null : _dtoMetadataCache.GetMetadataFor(property.Prop.PropertyType), Owner = operation.Value, OwnerMetadata = operation.ValueMetadata, OwnerPrimaryKeyColumn = operation.ValueMetadata.PrimaryKey.ColumnName, OwnerPropertyMetadata = property }); if (colBuff.Length > 0) { colBuff.Append(@", "); valBuff.Append(@", "); } colBuff.Append("[" + property.ColumnName + "]"); valBuff.Append("{"); valBuff.Append(index); valBuff.Append("}"); ++index; }
private static void AddUpdateOnParentTableForInsertDeleteOfManyToOneChildRow( IList<BaseOperation> operations, Difference diff, BaseInsertDeleteOperation insertOperation) { var updateOperation = new UpdateOperation { OwnerMetadata = insertOperation.OwnerMetadata, OwnerPropertyMetadata = insertOperation.OwnerPropertyMetadata, OwnerPrimaryKeyColumn = insertOperation.OwnerPrimaryKeyColumn, Owner = insertOperation.Owner, TableName = insertOperation.TableName, ColumnPropertyMetadata = diff.OwnerPropertyMetadata, ValueMetadata = diff.ValueMetadata, Value = diff.NewValue }; operations.Add(updateOperation); }
private static void InsertRecordInLinkTable(Script script, ref int paramIndex, BaseInsertDeleteOperation operation) { var linkTableName = operation.OwnerPropertyMetadata.GetAttribute <ManyToManyAttribute>().SchemaQualifiedLinkTableName; var parentPrimaryKeyColumn = operation.OwnerPrimaryKeyColumn; var childPrimaryKeyColumn = operation.ValueMetadata.PrimaryKey.Prop.Name; var parentPrimaryKeyGetter = new Func <object>( () => operation.OwnerPrimaryKeyAsObject); var childPrimaryKeyGetter = new Func <object>( () => operation.ValueMetadata.GetPrimaryKeyValueAsObject(operation.Value)); script.Buffer.Append(string.Format("IF NOT EXISTS (SELECT * FROM {0} WHERE [{1}] = ", linkTableName, parentPrimaryKeyColumn)); FormatWithParameter(script, "{0} AND ", ref paramIndex, null, parentPrimaryKeyGetter); script.Buffer.Append(string.Format("[{0}] = ", childPrimaryKeyColumn)); FormatWithParameter(script, @"{0}) BEGIN ", ref paramIndex, null, childPrimaryKeyGetter); script.Buffer.Append(string.Format( @" INSERT INTO {0} ( [{1}], [{2}] ) VALUES ( ", linkTableName, parentPrimaryKeyColumn, childPrimaryKeyColumn)); FormatWithParameter(script, @"{0}, {1} ); END ", ref paramIndex, null, // No wire-up required for link table parentPrimaryKeyGetter, childPrimaryKeyGetter); }
protected BaseInsertDeleteCommand(BaseInsertDeleteOperation operation) { _operation = operation; TableName = operation.TableName; PrimaryKeyColumn = operation.OwnerPrimaryKeyColumn; }
private static bool IsOneToOneRelationshipWithFkOnParent(BaseInsertDeleteOperation operation) { if (operation.OwnerPropertyMetadata.HasAttribute<OneToOneAttribute>() && operation.OwnerPropertyMetadata.HasAttribute<ForeignKeyReferenceAttribute>()) { if (operation.OwnerPropertyMetadata.GetAttribute<ForeignKeyReferenceAttribute>().ReferencedDto == operation.ValueMetadata.DtoType) { return true; } throw new ArgumentException(string.Format( "Invalid one to one relationship defined between parent {0} and child {1} " + "on property {2} of parent. " + "Parent has one to one relationship with [ForeignKeyReference] attribute " + "but type specified in [ForeignKeyReference] does not match child type. " + "Instead it is {3}. Change the type referenced by [ForeignKeyReference] " + "or change the type of the property to match that specified in " + "[ForeignKeyReference].", operation.OwnerMetadata.DtoType.FullName, operation.ValueMetadata.DtoType.FullName, operation.OwnerPropertyMetadata.Prop.Name, operation.OwnerPropertyMetadata.GetAttribute<ForeignKeyReferenceAttribute>().ReferencedDto.FullName), "operation"); } return false; }
private void AppendPropertyToInsertStatement( StringBuilder colBuff, StringBuilder valBuff, PropertyMetadata property, ref int index, BaseInsertDeleteOperation operation, ArrayList values, MethodInfo getter) { if (property.HasAttribute<ForeignKeyReferenceAttribute>() && null != operation.OwnerMetadata && _dtoMetadataCache.GetValidatedMetadataFor( property.GetAttribute<ForeignKeyReferenceAttribute>().ReferencedDto).TableName == operation.OwnerMetadata.TableName) { values.Add( new Func<object>(() => operation.OwnerPrimaryKeyAsObject)); } else if (property.HasAttribute<ManyToOneAttribute>() && property.GetAttribute<ManyToOneAttribute>().ForeignKeyTargetColumnName != null) { var propValue = property.GetValue(operation.Value); var propTypeMetadata = _dtoMetadataCache.GetValidatedMetadataFor(property.Prop.PropertyType); if (null != propValue && null != propTypeMetadata) { var targetName = property.GetAttribute<ManyToOneAttribute>().ForeignKeyTargetColumnName; var fkTargetProperty = propTypeMetadata[targetName]; if (fkTargetProperty == null) { throw new ArgumentException(string.Format( "Cannot INSERT foreign key value for non existent target column '{0}'" + " specified from column '{1}'.", targetName, property.ColumnName)); } values.Add(new Func<object>(() => fkTargetProperty.GetValue(propValue))); } else { values.Add(new Func<object>(() => null)); } } else if (property.HasAttribute<ManyToOneAttribute>() || property.HasAttribute<OneToOneAttribute>()) { if (property.HasAttribute<OneToOneAttribute>() && !property.HasAttribute<ForeignKeyReferenceAttribute>()) { // One to one relationship where child table references parent rather than the other way around. // This will be saved along with the child object. return; } object propValue = property.GetValue(operation.Value); DtoMetadata propMetadata = _dtoMetadataCache.GetValidatedMetadataFor(property.Prop.PropertyType); values.Add( new Func<object>( () => propValue == null || propMetadata == null ? null : propMetadata.GetPrimaryKeyValueAsObject(propValue))); } else { values.Add(getter.Invoke(operation.Value, new object[0])); } if (colBuff.Length > 0) { colBuff.Append(@", "); valBuff.Append(@", "); } colBuff.Append("[" + property.ColumnName + "]"); valBuff.Append("{"); valBuff.Append(index); valBuff.Append("}"); ++index; }
private void AppendPropertyToInsertStatement( Script script, StringBuilder colBuff, StringBuilder valBuff, PropertyMetadata property, ref int index, BaseInsertDeleteOperation operation, ArrayList values, MethodInfo getter, UpdateCommand updateCommand) { object columnValueForUpdate = null; if (property.HasAttribute<ForeignKeyReferenceAttribute>() && null != operation.OwnerMetadata && _dtoMetadataCache.GetValidatedMetadataFor( property.GetAttribute<ForeignKeyReferenceAttribute>().ReferencedDto).TableName == operation.OwnerMetadata.TableName) { columnValueForUpdate = new Func<object>(() => operation.OwnerPrimaryKeyAsObject); values.Add(columnValueForUpdate); } else if (property.HasAttribute<ManyToOneAttribute>() && property.GetAttribute<ManyToOneAttribute>().ForeignKeyTargetColumnName != null) { var propValue = property.GetValue(operation.Value); var propTypeMetadata = _dtoMetadataCache.GetValidatedMetadataFor(property.Prop.PropertyType); if (null != propValue && null != propTypeMetadata) { var targetName = property.GetAttribute<ManyToOneAttribute>().ForeignKeyTargetColumnName; var fkTargetProperty = propTypeMetadata[targetName]; if (fkTargetProperty == null) { throw new ArgumentException(string.Format( "Cannot INSERT foreign key value for non existent target column '{0}'" + " specified from column '{1}'.", targetName, property.ColumnName)); } columnValueForUpdate = new Func<object>(() => fkTargetProperty.GetValue(propValue)); values.Add(columnValueForUpdate); } else { columnValueForUpdate = new Func<object>(() => null); values.Add(columnValueForUpdate); } } else if (property.HasAttribute<ManyToOneAttribute>() || property.HasAttribute<OneToOneAttribute>()) { if (property.HasAttribute<OneToOneAttribute>() && !property.HasAttribute<ForeignKeyReferenceAttribute>()) { // One to one relationship where child table references parent rather than the other way around. // This will be saved along with the child object. return; } object propValue = property.GetValue(operation.Value); DtoMetadata propMetadata = _dtoMetadataCache.GetValidatedMetadataFor(property.Prop.PropertyType); columnValueForUpdate = new Func<object>( () => propValue == null || propMetadata == null ? null : propMetadata.GetPrimaryKeyValueAsObject(propValue)); values.Add(columnValueForUpdate); } else { columnValueForUpdate = getter.Invoke(operation.Value, new object[0]); values.Add(columnValueForUpdate); } if (columnValueForUpdate is Func<object>) { script.WireUpActions.Add(() => { object newPropertyValue = ((Func<object>) columnValueForUpdate)(); if (CanAssignToProperty(newPropertyValue, property)) { property.Prop.SetValue(operation.Value, newPropertyValue); } }); } updateCommand.AddOperation(new UpdateOperation() { ColumnPropertyMetadata = property, TableName = operation.ValueMetadata.TableName, Value = columnValueForUpdate, ValueMetadata = property.IsString || property.IsNumericType || property.IsEnum || ! property.IsReferenceType ? null : _dtoMetadataCache.GetMetadataFor(property.Prop.PropertyType), Owner = operation.Value, OwnerMetadata = operation.ValueMetadata, OwnerPrimaryKeyColumn = operation.ValueMetadata.PrimaryKey.ColumnName, OwnerPropertyMetadata = property }); if (colBuff.Length > 0) { colBuff.Append(@", "); valBuff.Append(@", "); } colBuff.Append("[" + property.ColumnName + "]"); valBuff.Append("{"); valBuff.Append(index); valBuff.Append("}"); ++index; }
private bool ShouldFilterOutForParticularCardinalitiesBecauseFkOnParent( BaseInsertDeleteOperation insertDeleteOperation) { if (insertDeleteOperation.OwnerPropertyMetadata != null) { if (insertDeleteOperation.OwnerPropertyMetadata.IsManyToOneRelationship) { return true; } if (insertDeleteOperation.OwnerPropertyMetadata.IsOneToOneRelationship && insertDeleteOperation.OwnerPropertyMetadata.HasAttribute<ForeignKeyReferenceAttribute>() && (insertDeleteOperation.ValueMetadata.IsReferenceData || insertDeleteOperation.OwnerPropertyMetadata.HasAttribute<ReferenceDataAttribute>()) && ! insertDeleteOperation.ValueMetadata.HasUpdateableForeignKeys) { return true; } } return false; }
private bool IsViableParentUpdateOnManyToOneRelationship( BaseInsertDeleteOperation insertDeleteOperation, Difference diff) { return insertDeleteOperation.OwnerMetadata != null && insertDeleteOperation.OwnerPropertyMetadata.IsManyToOneRelationship && diff.OldOwner != null && diff.NewOwner != null; }
private bool IsViableParentUpdateOnOneToOneWithFkInParent( BaseInsertDeleteOperation insertDeleteOperation, Difference diff) { return insertDeleteOperation.OwnerPropertyMetadata != null && diff.OldOwner != null && diff.NewOwner != null && (insertDeleteOperation.OwnerPropertyMetadata.IsOneToOneRelationship && insertDeleteOperation.OwnerPropertyMetadata.HasAttribute<ForeignKeyReferenceAttribute>()); }
private BaseOperation Transform(BaseInsertDeleteOperation baseInsertDelete) { if (baseInsertDelete.ValueMetadata != null) { if (baseInsertDelete.OwnerPropertyMetadata == null) { // Top level INSERT return(baseInsertDelete); } if (baseInsertDelete.OwnerPropertyMetadata.HasAttribute <ManyToManyAttribute>()) { // INSERT or DELETE record in link table; don't touch either entity table return(baseInsertDelete); } if (baseInsertDelete.OwnerPropertyMetadata.HasAttribute <OneToManyAttribute>()) { if (!baseInsertDelete.ValueMetadata.HasAttribute <ReferenceDataAttribute>() && !baseInsertDelete.OwnerPropertyMetadata.HasAttribute <ReferenceDataAttribute>()) { // INSERT or DELETE the value from the other table return(baseInsertDelete); } if ((baseInsertDelete.ValueMetadata.HasAttribute <ReferenceDataAttribute>() && !baseInsertDelete.ValueMetadata.HasUpdateableForeignKeys) || (baseInsertDelete.OwnerPropertyMetadata.HasAttribute <ReferenceDataAttribute>() && !baseInsertDelete.OwnerPropertyMetadata.GetAttribute <ReferenceDataAttribute>().HasUpdateableForeignKeys)) { throw new InvalidOperationException(string.Format( "You cannot INSERT into a reference data child table in a one to many relationship between a parent table and a child table where the child table does not have updateable foreign keys. (Note that any INSERT satisfying these conditions would be transformed into an UPDATE on the target row in the child table.) Attempted to INSERT into table {0}.", baseInsertDelete.ValueMetadata.TableName)); } } if (baseInsertDelete.OwnerPropertyMetadata.HasAttribute <OneToOneAttribute>()) { if (!baseInsertDelete.ValueMetadata.HasAttribute <ReferenceDataAttribute>() && !baseInsertDelete.OwnerPropertyMetadata.HasAttribute <ReferenceDataAttribute>()) { return(baseInsertDelete); } if (((baseInsertDelete.ValueMetadata.HasAttribute <ReferenceDataAttribute>() && !baseInsertDelete.ValueMetadata.HasUpdateableForeignKeys) || (baseInsertDelete.OwnerPropertyMetadata.HasAttribute <ReferenceDataAttribute>() && !baseInsertDelete.OwnerPropertyMetadata.GetAttribute <ReferenceDataAttribute>().HasUpdateableForeignKeys)) && !baseInsertDelete.OwnerPropertyMetadata.HasAttribute <ForeignKeyReferenceAttribute>()) { throw new InvalidOperationException(string.Format( "You cannot INSERT into a reference data child table in a one to one relationship between a parent table and a child table where te child table does not have updateable foreign keys. (Note that any INSERT satisfying these conditions would be transformed into an UPDATE on the target row in the child table.) Attempted to INSERT into table {0}.", baseInsertDelete.ValueMetadata.TableName)); } } } return(new UpdateOperation { ColumnPropertyMetadata = baseInsertDelete.OwnerPropertyMetadata, Value = baseInsertDelete.Value, ValueMetadata = baseInsertDelete.ValueMetadata, OwnerPrimaryKeyColumn = baseInsertDelete.OwnerPrimaryKeyColumn, Owner = baseInsertDelete.Owner, OwnerMetadata = baseInsertDelete.OwnerMetadata, OwnerPropertyMetadata = baseInsertDelete.OwnerPropertyMetadata, TableName = baseInsertDelete.TableName }); }
private BaseOperation Transform(BaseInsertDeleteOperation baseInsertDelete) { if (baseInsertDelete.ValueMetadata != null) { if (baseInsertDelete.OwnerPropertyMetadata == null) { // Top level INSERT return baseInsertDelete; } if (baseInsertDelete.OwnerPropertyMetadata.HasAttribute<ManyToManyAttribute>()) { // INSERT or DELETE record in link table; don't touch either entity table return baseInsertDelete; } if (baseInsertDelete.OwnerPropertyMetadata.HasAttribute<OneToManyAttribute>()) { if (!baseInsertDelete.ValueMetadata.HasAttribute<ReferenceDataAttribute>() && !baseInsertDelete.OwnerPropertyMetadata.HasAttribute<ReferenceDataAttribute>()) { // INSERT or DELETE the value from the other table return baseInsertDelete; } if ((baseInsertDelete.ValueMetadata.HasAttribute<ReferenceDataAttribute>() && !baseInsertDelete.ValueMetadata.HasUpdateableForeignKeys) || (baseInsertDelete.OwnerPropertyMetadata.HasAttribute<ReferenceDataAttribute>() && !baseInsertDelete.OwnerPropertyMetadata.GetAttribute<ReferenceDataAttribute>().HasUpdateableForeignKeys)) { throw new InvalidOperationException(string.Format( "You cannot INSERT into a reference data child table in a one to many relationship between a parent table and a child table where the child table does not have updateable foreign keys. (Note that any INSERT satisfying these conditions would be transformed into an UPDATE on the target row in the child table.) Attempted to INSERT into table {0}.", baseInsertDelete.ValueMetadata.TableName)); } } if (baseInsertDelete.OwnerPropertyMetadata.HasAttribute<OneToOneAttribute>()) { if (!baseInsertDelete.ValueMetadata.HasAttribute<ReferenceDataAttribute>() && !baseInsertDelete.OwnerPropertyMetadata.HasAttribute<ReferenceDataAttribute>()) { return baseInsertDelete; } if (((baseInsertDelete.ValueMetadata.HasAttribute<ReferenceDataAttribute>() && !baseInsertDelete.ValueMetadata.HasUpdateableForeignKeys) || (baseInsertDelete.OwnerPropertyMetadata.HasAttribute<ReferenceDataAttribute>() && !baseInsertDelete.OwnerPropertyMetadata.GetAttribute<ReferenceDataAttribute>().HasUpdateableForeignKeys)) && !baseInsertDelete.OwnerPropertyMetadata.HasAttribute<ForeignKeyReferenceAttribute>()) { throw new InvalidOperationException(string.Format( "You cannot INSERT into a reference data child table in a one to one relationship between a parent table and a child table where te child table does not have updateable foreign keys. (Note that any INSERT satisfying these conditions would be transformed into an UPDATE on the target row in the child table.) Attempted to INSERT into table {0}.", baseInsertDelete.ValueMetadata.TableName)); } } } return new UpdateOperation { ColumnPropertyMetadata = baseInsertDelete.OwnerPropertyMetadata, Value = baseInsertDelete.Value, ValueMetadata = baseInsertDelete.ValueMetadata, OwnerPrimaryKeyColumn = baseInsertDelete.OwnerPrimaryKeyColumn, Owner = baseInsertDelete.Owner, OwnerMetadata = baseInsertDelete.OwnerMetadata, OwnerPropertyMetadata = baseInsertDelete.OwnerPropertyMetadata, TableName = baseInsertDelete.TableName }; }
private static void InsertRecordInLinkTable(Script script, ref int paramIndex, BaseInsertDeleteOperation operation) { var linkTableName = operation.OwnerPropertyMetadata.GetAttribute<ManyToManyAttribute>().SchemaQualifiedLinkTableName; var parentPrimaryKeyColumn = operation.OwnerPrimaryKeyColumn; var childPrimaryKeyColumn = operation.ValueMetadata.PrimaryKey.Prop.Name; var parentPrimaryKeyGetter = new Func<object>( () => operation.OwnerPrimaryKeyAsObject); var childPrimaryKeyGetter = new Func<object>( () => operation.ValueMetadata.GetPrimaryKeyValueAsObject(operation.Value)); script.Buffer.Append(string.Format("IF NOT EXISTS (SELECT * FROM {0} WHERE [{1}] = ", linkTableName, parentPrimaryKeyColumn)); FormatWithParameter(script, "{0} AND ", ref paramIndex, null, parentPrimaryKeyGetter); script.Buffer.Append(string.Format("[{0}] = ", childPrimaryKeyColumn)); FormatWithParameter(script, @"{0}) BEGIN ", ref paramIndex, null, childPrimaryKeyGetter); script.Buffer.Append(string.Format( @" INSERT INTO {0} ( [{1}], [{2}] ) VALUES ( ", linkTableName, parentPrimaryKeyColumn, childPrimaryKeyColumn)); FormatWithParameter(script, @"{0}, {1} ); END ", ref paramIndex, null, // No wire-up required for link table parentPrimaryKeyGetter, childPrimaryKeyGetter); }