/// <summary> /// Application-level Business Object class /// </summary> public class ABusinessObject : mmBusinessObject { ... /// <summary> /// English singular name of the Business Object/Table record /// </summary> public string Name { get { return _name; } set { _name = value; } } private string _name = "record"; /// <summary> /// Check if record can be deleted, set rules /// </summary> /// <param name="dr"></param> /// <returns></returns> protected override bool HookPreDelete(DataRow dr) { bool result = true; // get number of restricted tables // +++ get English names of tables for messages int restrictedTableCount = this.CheckForeignTableDelete(dr); // Can't delete if (restrictedTableCount > 0) { // Add a broken rule mmBusinessRule Rules = this.GetBusinessRuleObject(); Rules.ClearAll(); // format message string errMsg = "Cannot delete this " + this.Name + ". " + restrictedTablesCount.ToString(); errMsg += restrictedTableCount == 1 ? " table has" : " tables have"; errMsg += " records dependent on it."; Rules.AddErrorProviderBrokenRule(null, errMsg); // return false so delete does not occur result = false; } return result; } /// <summary> /// check if foreign key relations prevent deletion of passed data row /// </summary> /// <param name="dr">DataRow containing foreign key value(s)</param> /// <returns>number of tables with restricted records</returns> /// <remarks> /// +++ this should be altered to handle compound keys /// +++ change to return string of English table names, /// perhaps from extended properties, or metadata table /// Only tested for MSSQL2005, /// The sp_fkeys stored procedure is equivalent to SQLForeignKeys in ODBC. /// </remarks> private int CheckForeignTableDelete(DataRow dr) { int restrictedTableCount = 0; // get foreign keys from catalog mmDataAccessBase DAO = this.GetDataAccessObject(); // see SQL 2005 docs for sp_fkeys // FKTABLE_NAME // FKCOLUMN_NAME // DELETE_RULE smallint 0 = cascade, 1 = restrict DataSet dsForeignKeys = new DataSet(); DAO.FillDataSet( dsForeignKeys, "sp_fkeys", "fk_table", CommandType.StoredProcedure, new IDbDataParameter[] { this.CreateParameter("@pktable_name", this.TableName) }, true); // for each table in dsForeignKeys, check if foreign key value exists if (dsForeignKeys != null && dsForeignKeys.Tables[0].Rows.Count > 0) { foreach (DataRow drForeignKeys in dsForeignKeys.Tables[0].Rows) { // if deletes are restricted, 1 = restrict if ( Convert.ToInt32( drForeignKeys["DELETE_RULE"] ) == 1) { // check if restricted records exist int exists = (int)DAO.ExecScalar( "IF EXISTS " + "(SELECT * FROM " + "[" + drForeignKeys["FKTABLE_NAME"].ToString() + "] WHERE [" + drForeignKeys["FKCOLUMN_NAME"].ToString() + "] = @fkvalue) " + "SELECT 1 ELSE SELECT 0", new IDbDataParameter[] { this.CreateParameter("@fkvalue", dr[this.PrimaryKey]) } ); if (exists == 1) { restrictedTableCount++; } } } } return restrictedTableCount; } }To show the error message in your form, you need code (elsewhere in this thread) like (in the delete button):
this.Result = mmButtonHelper.DeleteHandler(this, this.BindingSource, this.BindingSourceMember, ref this.BizObj); // if can't delete, show message if (this.Result == false) { mmBusinessObject bizObj = (mmBusinessObject)this.BizObj; mmBusinessRule Rules = bizObj.GetBusinessRuleObject(); if (Rules != null) { string ErrorMsg = Rules.GetAllBrokenRules(); if (!mmString.Empty(ErrorMsg)) { MessageBox.Show(ErrorMsg, "Can't Delete"); } } }Somewhat advanced:
/// <summary> /// extended MM business form /// </summary> public class myMaintenanceForm : mmMaintenanceForm { // ... public mmDataGridView NavDataGrid { get { return _navDataGrid; } set { _navDataGrid = value; } } private mmDataGridView _navDataGrid = null; // Called by delete menu tab delete tool strip button public override bool Delete() { return base.Delete((mmBusinessObject)this.PrimaryBizObj, (DataView)this.NavDataGrid.DataSource); // <-- NOTE passing DataView } }Changes to EACH maintenance form:
/// <summary> /// Summary description for GradeForm /// </summary> public partial class MyForm : myMaintenanceForm { // ... /// <summary> /// Constructor /// </summary> public MyForm() { // Instantiate and register business objects // ... InitializeComponent(); // ... // Register the DataGrid as the Navigation control this.NavControl = this.grdMyGrid; // NEW - Required for menutabs and ToolStripButtons when using DataViews!!! // Register the DataGrid as a reference for the form's Navigation DataSource this.NavDataGrid = this.grdMyGrid; // ... } // ... }Changes to subclass of mmToolStripButtonDelete:
/// <summary> /// ToolStrip Delete for myMaintenanceForm /// </summary> public partial class myToolStripButtonDelete : mmToolStripButtonDelete { public myToolStripButtonDelete () { InitializeComponent(); } public myToolStripButtonDelete (IContainer container) { container.Add(this); InitializeComponent(); } /// <summary> /// Delete click event /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected override void mmToolStripButtonDelete_Click(object sender, EventArgs e) { if (this.BindingFlag) { // Get a reference to the parent business form mmBusinessBaseForm ParentForm = mAppDesktop.FormMgr.GetParentBusinessForm(this); myMaintenanceForm Maintform = ParentForm as myMaintenanceForm; // set the binding to DefaultView of the NavDataGrid // code was: // this.Result = mmButtonHelper.DeleteHandler(this, this.BindingSource, // this.BindingSourceMember, ref this.BizObj); // BUT these bindings never got set // this.BindingSourceMember = "someDataView" will cause error // // old way, deprecated, still works //this.Result = mmButtonHelper.DeleteHandler(this, // Maintform.NavDataGrid.BindingSource, // Maintform.NavDataGrid.BindingSourceMember, ref this.BizObj); this.Result = Maintform.Delete(); // if can't delete, show message if (this.Result == false) { mmBusinessObject bizObj = (mmBusinessObject)Maintform.PrimaryBizObj; mmBusinessRule Rules = bizObj.GetBusinessRuleObject(); if (Rules != null) { string ErrorMsg = Rules.GetAllBrokenRules(); if (!mmString.Empty(ErrorMsg)) { MessageBox.Show(ErrorMsg, "Can't Delete"); } } } } } }Thanks!