internal override void CheckConstraint(DataRow childRow, DataRowAction action) { if ((action == DataRowAction.Change || action == DataRowAction.Add || action == DataRowAction.Rollback) && Table.DataSet != null && Table.DataSet.EnforceConstraints && childRow.HasKeyChanged(childKey)) { // This branch is for cascading case verification. DataRowVersion version = (action == DataRowAction.Rollback) ? DataRowVersion.Original : DataRowVersion.Current; object[] childKeyValues = childRow.GetKeyValues(childKey); // check to see if this is just a change to my parent's proposed value. if (childRow.HasVersion(version)) { // this is the new proposed value for the parent. DataRow parentRow = DataRelation.GetParentRow(this.ParentKey, this.ChildKey, childRow, version); if (parentRow != null && parentRow.inCascade) { object[] parentKeyValues = parentRow.GetKeyValues(parentKey, action == DataRowAction.Rollback ? version : DataRowVersion.Default); int parentKeyValuesRecord = childRow.Table.NewRecord(); childRow.Table.SetKeyValues(childKey, parentKeyValues, parentKeyValuesRecord); if (childKey.RecordsEqual(childRow.tempRecord, parentKeyValuesRecord)) { return; } } } // now check to see if someone exists... it will have to be in a parent row's current, not a proposed. object[] childValues = childRow.GetKeyValues(childKey); if (!IsKeyNull(childValues)) { Index parentIndex = parentKey.GetSortIndex(); if (!parentIndex.IsKeyInIndex(childValues)) { // could be self-join constraint if (childKey.Table == parentKey.Table && childRow.tempRecord != -1) { int lo = 0; for (lo = 0; lo < childValues.Length; lo++) { DataColumn column = parentKey.ColumnsReference[lo]; object value = column.ConvertValue(childValues[lo]); if (0 != column.CompareValueTo(childRow.tempRecord, value)) { break; } } if (lo == childValues.Length) { return; } } throw ExceptionBuilder.ForeignKeyViolation(ConstraintName, childKeyValues); } } } }
internal void SetNestedParentRow(DataRow parentRow, bool setNonNested) { if (parentRow == null) { this.SetParentRowToDBNull(); } else { foreach (DataRelation relation in this._table.ParentRelations) { if ((relation.Nested || setNonNested) && (relation.ParentKey.Table == parentRow._table)) { object[] keyValues = parentRow.GetKeyValues(relation.ParentKey); this.SetKeyValues(relation.ChildKey, keyValues); if (relation.Nested) { if (parentRow._table == this._table) { this.CheckForLoops(relation); } else { this.GetParentRow(relation); } } } } } }
public bool Invoke(DataRow row, DataRowVersion version) { object[] parentValues = GetParentValues(); if (parentValues == null) { return false; } object[] childValues = row.GetKeyValues(childKey, version); #if false for (int i = 0; i < keyValues.Length; i++) { Debug.WriteLine("keyvalues[" + (i).ToString() + "] = " + Convert.ToString(keyValues[i])); } for (int i = 0; i < values.Length; i++) { Debug.WriteLine("values[" + (i).ToString() + "] = " + Convert.ToString(values[i])); } #endif bool allow = true; if (childValues.Length != parentValues.Length) { allow = false; } else { for (int i = 0; i < childValues.Length; i++) { if (!childValues[i].Equals(parentValues[i])) { allow = false; break; } } } IFilter baseFilter = base.GetFilter(); if (baseFilter != null) { allow &= baseFilter.Invoke(row, version); } return allow; }
internal void CascadeRollback(DataRow row) { Index sortIndex = this.childKey.GetSortIndex((row.RowState == DataRowState.Deleted) ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); object[] keyValues = row.GetKeyValues(this.parentKey, (row.RowState == DataRowState.Modified) ? DataRowVersion.Current : DataRowVersion.Default); if (!this.IsKeyNull(keyValues)) { Range range = sortIndex.FindRecords(keyValues); if (this.acceptRejectRule == System.Data.AcceptRejectRule.Cascade) { if (!range.IsNull) { DataRow[] rows = sortIndex.GetRows(range); for (int i = 0; i < rows.Length; i++) { if (!rows[i].inCascade) { rows[i].RejectChanges(); } } } } else if (((((row.RowState != DataRowState.Deleted) && row.Table.DataSet.EnforceConstraints) && !range.IsNull) && ((range.Count != 1) || (sortIndex.GetRow(range.Min) != row))) && row.HasKeyChanged(this.parentKey)) { throw ExceptionBuilder.FailedCascadeUpdate(this.ConstraintName); } } }
public bool Invoke(DataRow row, DataRowVersion version) { object[] keyValues = row.GetKeyValues(this.key, version); bool flag = true; if (keyValues.Length != this.values.Length) { flag = false; } else { for (int i = 0; i < keyValues.Length; i++) { if (!keyValues[i].Equals(this.values[i])) { flag = false; break; } } } IFilter filter = base.GetFilter(); if (filter != null) { flag &= filter.Invoke(row, version); } return(flag); }
public bool Invoke(DataRow row, DataRowVersion version) { object[] parentValues = GetParentValues(); if (parentValues == null) { return false; } object[] childValues = row.GetKeyValues(_childKey, version); bool allow = true; if (childValues.Length != parentValues.Length) { allow = false; } else { for (int i = 0; i < childValues.Length; i++) { if (!childValues[i].Equals(parentValues[i])) { allow = false; break; } } } IFilter baseFilter = base.GetFilter(); if (baseFilter != null) { allow &= baseFilter.Invoke(row, version); } return allow; }
internal static DataRow?GetParentRow(DataKey parentKey, DataKey childKey, DataRow childRow, DataRowVersion version) { if (!childRow.HasVersion((version == DataRowVersion.Original) ? DataRowVersion.Original : DataRowVersion.Current)) { if (childRow._tempRecord == -1) { return(null); } } object[] values = childRow.GetKeyValues(childKey, version); if (IsKeyNull(values)) { return(null); } Index index = parentKey.GetSortIndex((version == DataRowVersion.Original) ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); Range range = index.FindRecords(values); if (range.IsNull) { return(null); } if (range.Count > 1) { throw ExceptionBuilder.MultipleParents(); } return(parentKey.Table._recordManager[index.GetRecord(range.Min)]); }
internal void CascadeCommit(DataRow row) { if (row.RowState == DataRowState.Detached) { return; } if (acceptRejectRule == AcceptRejectRule.Cascade) { Index childIndex = childKey.GetSortIndex(row.RowState == DataRowState.Deleted ? DataViewRowState.Deleted : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(parentKey, row.RowState == DataRowState.Deleted ? DataRowVersion.Original : DataRowVersion.Default); if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (!range.IsNull) { for (int j = range.Min; j <= range.Max; j++) { DataRow childRow = childIndex.GetRow(j); if (childRow.inCascade) { continue; } childRow.AcceptChanges(); } } } }
public void SetParentRow(DataRow parentRow, DataRelation relation) { if (relation == null) { this.SetParentRow(parentRow); } else if (parentRow == null) { this.SetParentRowToDBNull(relation); } else { if (this._table.DataSet != parentRow._table.DataSet) { throw ExceptionBuilder.ParentRowNotInTheDataSet(); } if (relation.ChildKey.Table != this._table) { throw ExceptionBuilder.SetParentRowTableMismatch(relation.ChildKey.Table.TableName, this._table.TableName); } if (relation.ParentKey.Table != parentRow._table) { throw ExceptionBuilder.SetParentRowTableMismatch(relation.ParentKey.Table.TableName, parentRow._table.TableName); } object[] keyValues = parentRow.GetKeyValues(relation.ParentKey); this.SetKeyValues(relation.ChildKey, keyValues); } }
internal override void CheckConstraint(DataRow childRow, DataRowAction action) { if (((((action == DataRowAction.Change) || (action == DataRowAction.Add)) || (action == DataRowAction.Rollback)) && ((this.Table.DataSet != null) && this.Table.DataSet.EnforceConstraints)) && childRow.HasKeyChanged(this.childKey)) { DataRowVersion version = (action == DataRowAction.Rollback) ? DataRowVersion.Original : DataRowVersion.Current; object[] keyValues = childRow.GetKeyValues(this.childKey); if (childRow.HasVersion(version)) { DataRow row = DataRelation.GetParentRow(this.ParentKey, this.ChildKey, childRow, version); if ((row != null) && row.inCascade) { object[] objArray2 = row.GetKeyValues(this.parentKey, (action == DataRowAction.Rollback) ? version : DataRowVersion.Default); int record = childRow.Table.NewRecord(); childRow.Table.SetKeyValues(this.childKey, objArray2, record); if (this.childKey.RecordsEqual(childRow.tempRecord, record)) { return; } } } object[] values = childRow.GetKeyValues(this.childKey); if (!this.IsKeyNull(values) && !this.parentKey.GetSortIndex().IsKeyInIndex(values)) { if ((this.childKey.Table == this.parentKey.Table) && (childRow.tempRecord != -1)) { int index = 0; index = 0; while (index < values.Length) { DataColumn column = this.parentKey.ColumnsReference[index]; object obj2 = column.ConvertValue(values[index]); if (column.CompareValueTo(childRow.tempRecord, obj2) != 0) { break; } index++; } if (index == values.Length) { return; } } throw ExceptionBuilder.ForeignKeyViolation(this.ConstraintName, keyValues); } } }
internal static DataRow[] GetParentRows(DataKey parentKey, DataKey childKey, DataRow childRow, DataRowVersion version) { object[] keyValues = childRow.GetKeyValues(childKey, version); if (IsKeyNull(keyValues)) { return(parentKey.Table.NewRowArray(0)); } return(parentKey.GetSortIndex((version == DataRowVersion.Original) ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows).GetRows(keyValues)); }
/// <include file='doc\DataRelation.uex' path='docs/doc[@for="DataRelation.GetParentRows"]/*' /> /// <devdoc> /// Gets the parent rows for the given child row across the relation using the version given /// </devdoc> internal static DataRow[] GetParentRows(DataKey parentKey, DataKey childKey, DataRow childRow, DataRowVersion version) { object[] values = childRow.GetKeyValues(childKey, version); if (IsKeyNull(values)) { return(parentKey.Table.NewRowArray(0)); } Index index = parentKey.GetSortIndex(); return(index.GetRows(values)); }
internal void CascadeRollback(DataRow row) { Debug.Assert(row.Table.DataSet != null); Index childIndex = _childKey.GetSortIndex(row.RowState == DataRowState.Deleted ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(_parentKey, row.RowState == DataRowState.Modified ? DataRowVersion.Current : DataRowVersion.Default); if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (_acceptRejectRule == AcceptRejectRule.Cascade) { if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { if (rows[j]._inCascade) { continue; } rows[j].RejectChanges(); } } } else { // AcceptRejectRule.None if (row.RowState != DataRowState.Deleted && row.Table.DataSet.EnforceConstraints) { if (!range.IsNull) { if (range.Count == 1 && childIndex.GetRow(range.Min) == row) { return; } if (row.HasKeyChanged(_parentKey)) {// if key is not changed, this will not cause child to be stranded throw ExceptionBuilder.FailedCascadeUpdate(ConstraintName); } } } } }
internal void SetParentRowRecords(DataRow childRow, DataRow parentRow) { object[] parentKeyValues = parentRow.GetKeyValues(ParentKey); if (childRow._tempRecord != -1) { ChildTable._recordManager.SetKeyValues(childRow._tempRecord, ChildKey, parentKeyValues); } if (childRow._newRecord != -1) { ChildTable._recordManager.SetKeyValues(childRow._newRecord, ChildKey, parentKeyValues); } if (childRow._oldRecord != -1) { ChildTable._recordManager.SetKeyValues(childRow._oldRecord, ChildKey, parentKeyValues); } }
internal void SetParentRowRecords(DataRow childRow, DataRow parentRow) { object[] keyValues = parentRow.GetKeyValues(this.ParentKey); if (childRow.tempRecord != -1) { this.ChildTable.recordManager.SetKeyValues(childRow.tempRecord, this.ChildKey, keyValues); } if (childRow.newRecord != -1) { this.ChildTable.recordManager.SetKeyValues(childRow.newRecord, this.ChildKey, keyValues); } if (childRow.oldRecord != -1) { this.ChildTable.recordManager.SetKeyValues(childRow.oldRecord, this.ChildKey, keyValues); } }
internal void CascadeRollback(DataRow row) { Index childIndex = childKey.GetSortIndex(row.RowState == DataRowState.Deleted ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(parentKey, row.RowState == DataRowState.Modified ? DataRowVersion.Current : DataRowVersion.Default); // Bug : This is definitely not a proper fix. (Ref. MDAC Bug 73592) if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (acceptRejectRule == AcceptRejectRule.Cascade) { if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { if (rows[j].inCascade) { continue; } rows[j].RejectChanges(); } } } else { // AcceptRejectRule.None if (row.RowState != DataRowState.Deleted && row.Table.DataSet.EnforceConstraints) { if (!range.IsNull) { if (range.Count == 1 && childIndex.GetRow(range.Min) == row) { return; } throw ExceptionBuilder.FailedCascadeUpdate(ConstraintName); } } } }
public bool Invoke(DataRow row, DataRowVersion version) { object[] parentValues = GetParentValues(); if (parentValues == null) { return(false); } object[] childValues = row.GetKeyValues(childKey, version); #if false for (int i = 0; i < keyValues.Length; i++) { Debug.WriteLine("keyvalues[" + (i).ToString() + "] = " + Convert.ToString(keyValues[i])); } for (int i = 0; i < values.Length; i++) { Debug.WriteLine("values[" + (i).ToString() + "] = " + Convert.ToString(values[i])); } #endif bool allow = true; if (childValues.Length != parentValues.Length) { allow = false; } else { for (int i = 0; i < childValues.Length; i++) { if (!childValues[i].Equals(parentValues[i])) { allow = false; break; } } } IFilter baseFilter = base.GetFilter(); if (baseFilter != null) { allow &= baseFilter.Invoke(row, version); } return(allow); }
public bool Invoke(DataRow row, DataRowVersion version) { object[]? parentValues = GetParentValues(); if (parentValues == null) { return(false); } object[] childValues = row.GetKeyValues(_childKey, version); bool allow = childValues.AsSpan().SequenceEqual(parentValues); IFilter?baseFilter = base.GetFilter(); if (baseFilter != null) { allow &= baseFilter.Invoke(row, version); } return(allow); }
internal void CascadeCommit(DataRow row) { if ((row.RowState != DataRowState.Detached) && (this.acceptRejectRule == System.Data.AcceptRejectRule.Cascade)) { Index sortIndex = this.childKey.GetSortIndex((row.RowState == DataRowState.Deleted) ? DataViewRowState.Deleted : DataViewRowState.CurrentRows); object[] keyValues = row.GetKeyValues(this.parentKey, (row.RowState == DataRowState.Deleted) ? DataRowVersion.Original : DataRowVersion.Default); if (!this.IsKeyNull(keyValues)) { Range range = sortIndex.FindRecords(keyValues); if (!range.IsNull) { foreach (DataRow row2 in sortIndex.GetRows(range)) { if ((DataRowState.Detached != row2.RowState) && !row2.inCascade) { row2.AcceptChanges(); } } } } } }
/// <include file='doc\DataRow.uex' path='docs/doc[@for="DataRow.SetParentRow"]/*' /> /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> public void SetParentRow(DataRow parentRow) { if (parentRow == null) { SetParentRowToDBNull(); return; } if (this.Table == null) { throw ExceptionBuilder.ChildRowNotInTheTable(); } if (parentRow.Table == null) { throw ExceptionBuilder.ParentRowNotInTheTable(); } foreach (DataRelation relation in this.Table.ParentRelations) { if (relation.ParentKey.Table == parentRow.Table) { object[] parentKeyValues = parentRow.GetKeyValues(relation.ParentKey); this.SetKeyValues(relation.ChildKey, parentKeyValues); if (relation.Nested) { if (parentRow.Table == this.Table) { this.CheckForLoops(relation); } else { this.GetParentRow(relation); } } } } }
public bool Invoke(DataRow row, DataRowVersion version) { object[] parentValues = GetParentValues(); if (parentValues == null) { return(false); } object[] childValues = row.GetKeyValues(_childKey, version); bool allow = true; if (childValues.Length != parentValues.Length) { allow = false; } else { for (int i = 0; i < childValues.Length; i++) { if (!childValues[i].Equals(parentValues[i])) { allow = false; break; } } } IFilter baseFilter = base.GetFilter(); if (baseFilter != null) { allow &= baseFilter.Invoke(row, version); } return(allow); }
internal void CascadeCommit(DataRow row) { if (row.RowState == DataRowState.Detached) { return; } if (_acceptRejectRule == AcceptRejectRule.Cascade) { Index childIndex = _childKey.GetSortIndex(row.RowState == DataRowState.Deleted ? DataViewRowState.Deleted : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(_parentKey, row.RowState == DataRowState.Deleted ? DataRowVersion.Original : DataRowVersion.Default); if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (!range.IsNull) { // Self-referencing table has suspendIndexEvents, in the multi-table scenario the child table hasn't // this allows the self-ref table to maintain the index while in the child-table doesn't DataRow[] rows = childIndex.GetRows(range); foreach (DataRow childRow in rows) { if (DataRowState.Detached != childRow.RowState) { if (childRow._inCascade) { continue; } childRow.AcceptChanges(); } } } } }
internal void CascadeDelete(DataRow row) { if (-1 == row._newRecord) { return; } object[] currentKey = row.GetKeyValues(_parentKey, DataRowVersion.Current); if (IsKeyNull(currentKey)) { return; } Index childIndex = _childKey.GetSortIndex(); switch (DeleteRule) { case Rule.None: { if (row.Table.DataSet.EnforceConstraints) { // if we're not cascading deletes, we should throw if we're going to strand a child row under enforceConstraints. Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { if (range.Count == 1 && childIndex.GetRow(range.Min) == row) { return; } throw ExceptionBuilder.FailedCascadeDelete(ConstraintName); } } break; } case Rule.Cascade: { object[] key = row.GetKeyValues(_parentKey, DataRowVersion.Default); Range range = childIndex.FindRecords(key); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { DataRow r = rows[j]; if (r._inCascade) { continue; } r.Table.DeleteRow(r); } } break; } case Rule.SetNull: { object[] proposedKey = new object[_childKey.ColumnsReference.Length]; for (int i = 0; i < _childKey.ColumnsReference.Length; i++) { proposedKey[i] = DBNull.Value; } Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; if (row != rows[j]) { rows[j].SetKeyValues(_childKey, proposedKey); } } } break; } case Rule.SetDefault: { object[] proposedKey = new object[_childKey.ColumnsReference.Length]; for (int i = 0; i < _childKey.ColumnsReference.Length; i++) { proposedKey[i] = _childKey.ColumnsReference[i].DefaultValue; } Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; if (row != rows[j]) { rows[j].SetKeyValues(_childKey, proposedKey); } } } break; } default: { Debug.Fail("Unknown Rule value"); break; } } }
internal void SetParentRowRecords(DataRow childRow, DataRow parentRow) { object[] parentKeyValues = parentRow.GetKeyValues(ParentKey); if (childRow.tempRecord != -1) { ChildTable.recordManager.SetKeyValues(childRow.tempRecord, ChildKey, parentKeyValues); } if (childRow.newRecord != -1) { ChildTable.recordManager.SetKeyValues(childRow.newRecord, ChildKey, parentKeyValues); } if (childRow.oldRecord != -1) { ChildTable.recordManager.SetKeyValues(childRow.oldRecord, ChildKey, parentKeyValues); } }
internal static DataRow GetParentRow(DataKey parentKey, DataKey childKey, DataRow childRow, DataRowVersion version) { if (!childRow.HasVersion((version == DataRowVersion.Original) ? DataRowVersion.Original : DataRowVersion.Current)) if (childRow.tempRecord == -1) return null; object[] values = childRow.GetKeyValues(childKey, version); if (IsKeyNull(values)) { return null; } Index index = parentKey.GetSortIndex((version == DataRowVersion.Original) ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); Range range = index.FindRecords(values); if (range.IsNull) { return null; } if (range.Count > 1) { throw ExceptionBuilder.MultipleParents(); } return parentKey.Table.recordManager[index.GetRecord(range.Min)]; }
internal void CascadeUpdate(DataRow row) { if (-1 != row.newRecord) { object[] keyValues = row.GetKeyValues(this.parentKey, DataRowVersion.Current); if (this.Table.DataSet.fInReadXml || !this.IsKeyNull(keyValues)) { Index sortIndex = this.childKey.GetSortIndex(); switch (this.UpdateRule) { case Rule.None: if (row.Table.DataSet.EnforceConstraints && !sortIndex.FindRecords(keyValues).IsNull) { throw ExceptionBuilder.FailedCascadeUpdate(this.ConstraintName); } return; case Rule.Cascade: { Range range3 = sortIndex.FindRecords(keyValues); if (!range3.IsNull) { object[] objArray4 = row.GetKeyValues(this.parentKey, DataRowVersion.Proposed); DataRow[] rows = sortIndex.GetRows(range3); for (int i = 0; i < rows.Length; i++) { rows[i].SetKeyValues(this.childKey, objArray4); } } return; } case Rule.SetNull: { object[] objArray3 = new object[this.childKey.ColumnsReference.Length]; for (int j = 0; j < this.childKey.ColumnsReference.Length; j++) { objArray3[j] = DBNull.Value; } Range range2 = sortIndex.FindRecords(keyValues); if (!range2.IsNull) { DataRow[] rowArray2 = sortIndex.GetRows(range2); for (int k = 0; k < rowArray2.Length; k++) { rowArray2[k].SetKeyValues(this.childKey, objArray3); } } return; } case Rule.SetDefault: { object[] objArray2 = new object[this.childKey.ColumnsReference.Length]; for (int m = 0; m < this.childKey.ColumnsReference.Length; m++) { objArray2[m] = this.childKey.ColumnsReference[m].DefaultValue; } Range range = sortIndex.FindRecords(keyValues); if (!range.IsNull) { DataRow[] rowArray = sortIndex.GetRows(range); for (int n = 0; n < rowArray.Length; n++) { rowArray[n].SetKeyValues(this.childKey, objArray2); } } return; } } } } }
internal void CascadeDelete(DataRow row) { if (-1 != row.newRecord) { object[] keyValues = row.GetKeyValues(this.parentKey, DataRowVersion.Current); if (!this.IsKeyNull(keyValues)) { Index sortIndex = this.childKey.GetSortIndex(); switch (this.DeleteRule) { case Rule.None: if (row.Table.DataSet.EnforceConstraints) { Range range4 = sortIndex.FindRecords(keyValues); if (range4.IsNull) { return; } if ((range4.Count != 1) || (sortIndex.GetRow(range4.Min) != row)) { throw ExceptionBuilder.FailedCascadeDelete(this.ConstraintName); } } return; case Rule.Cascade: { object[] key = row.GetKeyValues(this.parentKey, DataRowVersion.Default); Range range3 = sortIndex.FindRecords(key); if (!range3.IsNull) { foreach (DataRow row2 in sortIndex.GetRows(range3)) { if (!row2.inCascade) { row2.Table.DeleteRow(row2); } } } return; } case Rule.SetNull: { object[] objArray3 = new object[this.childKey.ColumnsReference.Length]; for (int i = 0; i < this.childKey.ColumnsReference.Length; i++) { objArray3[i] = DBNull.Value; } Range range2 = sortIndex.FindRecords(keyValues); if (!range2.IsNull) { DataRow[] rows = sortIndex.GetRows(range2); for (int j = 0; j < rows.Length; j++) { if (row != rows[j]) { rows[j].SetKeyValues(this.childKey, objArray3); } } } return; } case Rule.SetDefault: { object[] objArray2 = new object[this.childKey.ColumnsReference.Length]; for (int k = 0; k < this.childKey.ColumnsReference.Length; k++) { objArray2[k] = this.childKey.ColumnsReference[k].DefaultValue; } Range range = sortIndex.FindRecords(keyValues); if (!range.IsNull) { DataRow[] rowArray = sortIndex.GetRows(range); for (int m = 0; m < rowArray.Length; m++) { if (row != rowArray[m]) { rowArray[m].SetKeyValues(this.childKey, objArray2); } } } return; } } } } }
internal void CascadeUpdate(DataRow row) { if (-1 == row.newRecord) return; object[] currentKey = row.GetKeyValues(parentKey, DataRowVersion.Current); if (!Table.DataSet.fInReadXml && IsKeyNull(currentKey)) { return; } Index childIndex = childKey.GetSortIndex(); switch (UpdateRule) { case Rule.None: { if (row.Table.DataSet.EnforceConstraints) { // if we're not cascading deletes, we should throw if we're going to strand a child row under enforceConstraints. Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { throw ExceptionBuilder.FailedCascadeUpdate(ConstraintName); } } break; } case Rule.Cascade: { Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { object[] proposedKey = row.GetKeyValues(parentKey, DataRowVersion.Proposed); DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } case Rule.SetNull: { object[] proposedKey = new object[childKey.ColumnsReference.Length]; for (int i = 0; i < childKey.ColumnsReference.Length; i++) proposedKey[i] = DBNull.Value; Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } case Rule.SetDefault: { object[] proposedKey = new object[childKey.ColumnsReference.Length]; for (int i = 0; i < childKey.ColumnsReference.Length; i++) proposedKey[i] = childKey.ColumnsReference[i].DefaultValue; Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } default: { Debug.Assert(false, "Unknown Rule value"); break; } } }
internal void CascadeCommit(DataRow row) { if (row.RowState == DataRowState.Detached) return; if (acceptRejectRule == AcceptRejectRule.Cascade) { Index childIndex = childKey.GetSortIndex( row.RowState == DataRowState.Deleted ? DataViewRowState.Deleted : DataViewRowState.CurrentRows ); object[] key = row.GetKeyValues(parentKey, row.RowState == DataRowState.Deleted ? DataRowVersion.Original : DataRowVersion.Default ); if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (!range.IsNull) { // SQLBU 499726 - DataTable internal index is corrupted: '13' // Self-referencing table has suspendIndexEvents, in the multi-table scenario the child table hasn't // this allows the self-ref table to maintain the index while in the child-table doesn't DataRow[] rows = childIndex.GetRows(range); foreach(DataRow childRow in rows) { if (DataRowState.Detached != childRow.RowState) { if (childRow.inCascade) continue; childRow.AcceptChanges(); } } } } }
/// <summary> /// Sets current row's parent row with specified relation. /// </summary> public void SetParentRow(DataRow parentRow, DataRelation relation) { if (relation == null) { SetParentRow(parentRow); return; } if (parentRow == null) { SetParentRowToDBNull(relation); return; } if (_table.DataSet != parentRow._table.DataSet) { throw ExceptionBuilder.ParentRowNotInTheDataSet(); } if (relation.ChildKey.Table != _table) { throw ExceptionBuilder.SetParentRowTableMismatch(relation.ChildKey.Table.TableName, _table.TableName); } if (relation.ParentKey.Table != parentRow._table) { throw ExceptionBuilder.SetParentRowTableMismatch(relation.ParentKey.Table.TableName, parentRow._table.TableName); } object[] parentKeyValues = parentRow.GetKeyValues(relation.ParentKey); SetKeyValues(relation.ChildKey, parentKeyValues); }
internal void CascadeUpdate(DataRow row) { if (-1 == row.newRecord) { return; } object[] currentKey = row.GetKeyValues(parentKey, DataRowVersion.Current); if (!Table.DataSet.fInReadXml && IsKeyNull(currentKey)) { return; } Index childIndex = childKey.GetSortIndex(); switch (UpdateRule) { case Rule.None: { if (row.Table.DataSet.EnforceConstraints) { // if we're not cascading deletes, we should throw if we're going to strand a child row under enforceConstraints. Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { throw ExceptionBuilder.FailedCascadeUpdate(ConstraintName); } } break; } case Rule.Cascade: { Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { object[] proposedKey = row.GetKeyValues(parentKey, DataRowVersion.Proposed); DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } case Rule.SetNull: { object[] proposedKey = new object[childKey.Columns.Length]; for (int i = 0; i < childKey.Columns.Length; i++) { proposedKey[i] = DBNull.Value; } Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } case Rule.SetDefault: { object[] proposedKey = new object[childKey.Columns.Length]; for (int i = 0; i < childKey.Columns.Length; i++) { proposedKey[i] = childKey.Columns[i].DefaultValue; } Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } default: { Debug.Assert(false, "Unknown Rule value"); break; } } }
internal void CascadeRollback(DataRow row) { Index childIndex = childKey.GetSortIndex( row.RowState == DataRowState.Deleted ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(parentKey, row.RowState == DataRowState.Modified ? DataRowVersion.Current : DataRowVersion.Default ); // if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (acceptRejectRule == AcceptRejectRule.Cascade) { if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { if (rows[j].inCascade) continue; rows[j].RejectChanges(); } } } else { // AcceptRejectRule.None if (row.RowState != DataRowState.Deleted && row.Table.DataSet.EnforceConstraints) { if (!range.IsNull) { if (range.Count == 1 && childIndex.GetRow(range.Min) == row) return; if (row.HasKeyChanged(parentKey)) {// if key is not changed, this will not cause child to be stranded throw ExceptionBuilder.FailedCascadeUpdate(ConstraintName); } } } } }
internal override void CheckConstraint(DataRow childRow, DataRowAction action) { if ((action == DataRowAction.Change || action == DataRowAction.Add || action == DataRowAction.Rollback) && Table.DataSet != null && Table.DataSet.EnforceConstraints && childRow.HasKeyChanged(childKey)) { // This branch is for cascading case verification. DataRowVersion version = (action == DataRowAction.Rollback) ? DataRowVersion.Original : DataRowVersion.Current; object[] childKeyValues = childRow.GetKeyValues(childKey); // check to see if this is just a change to my parent's proposed value. if (childRow.HasVersion(version)) { // this is the new proposed value for the parent. DataRow parentRow = DataRelation.GetParentRow(this.ParentKey, this.ChildKey, childRow, version); if(parentRow != null && parentRow.inCascade) { object[] parentKeyValues = parentRow.GetKeyValues(parentKey, action == DataRowAction.Rollback ? version : DataRowVersion.Default); int parentKeyValuesRecord = childRow.Table.NewRecord(); childRow.Table.SetKeyValues(childKey, parentKeyValues, parentKeyValuesRecord); if (childKey.RecordsEqual(childRow.tempRecord, parentKeyValuesRecord)) { return; } } } // now check to see if someone exists... it will have to be in a parent row's current, not a proposed. object[] childValues = childRow.GetKeyValues(childKey); if (!IsKeyNull(childValues)) { Index parentIndex = parentKey.GetSortIndex(); if (!parentIndex.IsKeyInIndex(childValues)) { // could be self-join constraint if (childKey.Table == parentKey.Table && childRow.tempRecord != -1) { int lo = 0; for (lo = 0; lo < childValues.Length; lo++) { DataColumn column = parentKey.ColumnsReference[lo]; object value = column.ConvertValue(childValues[lo]); if (0 != column.CompareValueTo(childRow.tempRecord, value)) { break; } } if (lo == childValues.Length) { return; } } throw ExceptionBuilder.ForeignKeyViolation(ConstraintName, childKeyValues); } } } }
internal void SetNestedParentRow(DataRow parentRow, bool setNonNested) { if (parentRow == null) { SetParentRowToDBNull(); return; } foreach (DataRelation relation in _table.ParentRelations) { if (relation.Nested || setNonNested) { if (relation.ParentKey.Table == parentRow._table) { object[] parentKeyValues = parentRow.GetKeyValues(relation.ParentKey); SetKeyValues(relation.ChildKey, parentKeyValues); if (relation.Nested) { if (parentRow._table == _table) { CheckForLoops(relation); } else { GetParentRow(relation); } } } } } }
/// <devdoc> /// Gets the parent rows for the given child row across the relation using the version given /// </devdoc> internal static DataRow[] GetParentRows(DataKey parentKey, DataKey childKey, DataRow childRow, DataRowVersion version) { object[] values = childRow.GetKeyValues(childKey, version); if (IsKeyNull(values)) { return parentKey.Table.NewRowArray(0); } Index index = parentKey.GetSortIndex((version == DataRowVersion.Original) ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); return index.GetRows(values); }
internal override void CheckConstraint(DataRow childRow, DataRowAction action) { Debug.Assert(Table.DataSet != null, "Relation " + ConstraintName + " isn't part of a DataSet, so this check shouldn't be happening."); if ((action == DataRowAction.Change || action == DataRowAction.Add || action == DataRowAction.Rollback) && Table.DataSet != null && Table.DataSet.EnforceConstraints && childRow.HasKeyChanged(childKey)) { // This branch is for cascading case verification. DataRowVersion version = (action == DataRowAction.Rollback) ? DataRowVersion.Original : DataRowVersion.Current; object[] childKeyValues = childRow.GetKeyValues(childKey); // check to see if this is just a change to my parent's proposed value. if (childRow.HasVersion(version)) { // this is the new proposed value for the parent. DataRow parentRow = DataRelation.GetParentRow(this.ParentKey, this.ChildKey, childRow, version); if (parentRow != null && parentRow.inCascade) { object[] parentKeyValues = parentRow.GetKeyValues(parentKey, action == DataRowAction.Rollback ? version : DataRowVersion.Default); #if DEBUG if (CompModSwitches.Data_Constraints.TraceVerbose) { Debug.WriteLine("Parent and Child values on constraint check."); for (int i = 0; i < childKeyValues.Length; i++) { Debug.WriteLine("... " + i.ToString() + ": " + Convert.ToString(parentKeyValues[i]) + ", " + Convert.ToString(childKeyValues[i])); } } #endif int parentKeyValuesRecord = childRow.Table.NewRecord(); childRow.Table.SetKeyValues(childKey, parentKeyValues, parentKeyValuesRecord); if (childKey.RecordsEqual(childRow.tempRecord, parentKeyValuesRecord)) { return; } } } // now check to see if someone exists... it will have to be in a parent row's current, not a proposed. object[] childValues = childRow.GetKeyValues(childKey); if (!IsKeyNull(childValues)) { Index parentIndex = parentKey.GetSortIndex(); if (!parentIndex.IsKeyInIndex(childValues)) { // could be self-join constraint if (childKey.Table == parentKey.Table && childRow.tempRecord != -1) { int lo = 0; for (lo = 0; lo < childValues.Length; lo++) { if (parentKey.Columns[lo].CompareToValue(childRow.tempRecord, childValues[lo]) != 0) { break; } } if (lo == childValues.Length) { return; } } throw ExceptionBuilder.ForeignKeyViolation(ConstraintName, childKeyValues); } } } }
internal static DataRow[] GetChildRows(DataKey parentKey, DataKey childKey, DataRow parentRow, DataRowVersion version) { object[] keyValues = parentRow.GetKeyValues(parentKey, version); if (IsKeyNull(keyValues)) { return childKey.Table.NewRowArray(0); } return childKey.GetSortIndex((version == DataRowVersion.Original) ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows).GetRows(keyValues); }