/// <summary> /// updates the db row identified by the panel PK, using data from panel fields /// </summary> /// <param name="panel"></param> // TODO : row PK cannot change once created! public void UpdatePanel(Panel panel) { CheckAgainstOriginalDataRow(panel); foreach (IField f in panel.fields) { if (f is IColumnField) { IColumnField cf = (IColumnField)f; if (cf.Unique && panel.RetrievedManagedData[cf.ColumnName] != null) // TODO make sure all fields are set to null when should be { bool unique = driver.CheckUniqueness(panel.tableName, cf.ColumnName, panel.RetrievedManagedData[cf.ColumnName], panel.PK); if (!unique) { throw new ConstraintException("Field \"" + cf.Data + "\" is restrained to be unique and \"" + cf.Data.ToString() + "\" is already present"); } } } } foreach (DataColumn PKcol in panel.PK.Table.Columns) // row PK midified { if (panel.PK[PKcol.ColumnName].ToString() != panel.RetrievedManagedData[PKcol.ColumnName].ToString()) { throw new WebDriverValidationException("The field '" + PKcol.ColumnName + "' is a part of the item`s identity and cannot be changed unless the item is recreated."); } } try { driver.BeginTransaction(); int affected = driver.query("UPDATE " + panel.tableName + " SET ", dbe.UpdVals(panel.RetrievedInsertData), " WHERE ", dbe.Condition(panel.PK)); if (affected > 1) { driver.RollbackTransaction(); throw new Exception("Panel PK not unique, trying to update multiple rows at a time!"); } driver.CommitTransaction(); } catch (ConstraintException ce) { driver.RollbackTransaction(); throw new ConstraintException(FriendlyConstraintException(ce.Message, panel), null); } foreach (IField f in panel.fields) { if (f is M2NMappingField) { M2NMappingField m2nf = (M2NMappingField)f; int ID = (int)panel.PK[m2nf.Mapping.myColumn]; UnmapM2NMappingKey(m2nf.Mapping, ID); MapM2NVals(m2nf.Mapping, ID, (List <int>)m2nf.Data); } } }
/// <summary> /// inserts a new row into the table managed by the panel, with the vlaues stored in it`s fields, also inserts in mapping tables /// </summary> /// <param name="panel"></param> /// <returns></returns> public int InsertIntoPanel(Panel panel) { foreach (IField f in panel.fields) { if (f is IColumnField) { IColumnField cf = (IColumnField)f; if (panel.RetrievedManagedData[cf.ColumnName] != null && cf.Unique) { bool unique = driver.CheckUniqueness(panel.tableName, cf.ColumnName, panel.RetrievedManagedData[cf.ColumnName]); if (!unique) { throw new ConstraintException("Field \"" + cf.Caption + "\" is restrained to be unique and \"" + cf.Data.ToString() + "\" is already present"); } } } } int ID; try { driver.BeginTransaction(); driver.query("INSERT INTO ", dbe.Table(panel.tableName), dbe.InsVals(panel.RetrievedInsertData)); ID = driver.LastId(); // TODO safe? Does transaction ensure insert separation? driver.CommitTransaction(); } catch (MySql.Data.MySqlClient.MySqlException mye) { // Can occur, if there is a unique Key on multiple columns - such constraint cannot be set in panel management // (very rare indeed). The exception is attached a user-friendly comment and bubbles to the Show.cs, where // it will be displayed as a standard validation error (but probably with a notable delay). // will already be out of transaction - BaseDriver closes it immediately //if(IsInTransaction) // driver.RollbackTransaction(); throw new ConstraintException(FriendlyConstraintException(mye.Message, panel), null); } foreach (IField f in panel.fields) { if (f is M2NMappingField) { M2NMappingField m2nf = (M2NMappingField)f; MapM2NVals(m2nf.Mapping, ID, (List <int>)m2nf.Data); } } return(ID); }
public void FillPanelFKOptions(Panel panel) { foreach (IField field in panel.fields) { if (field is FKField) { // FK options FKField fkf = (FKField)field; fkf.FKOptions = FetchFKOptions(fkf.FK); } else if (field is M2NMappingField) { M2NMappingField m2nf = (M2NMappingField)field; m2nf.FKOptions = FetchFKOptions((FK)m2nf.Mapping); } } //foreach (Panel p in panel.children) //FillPanelFks(p); }
/// <summary> /// Fills panel with data based on the columns included and possibly the Primary Key /// </summary> /// <param name="panel"></param> public void FillPanel(Panel panel) { if (panel.fields.Count() > 0) { // editable Panel, fetch the DataRow, simple controls - must have unique PK var columns = panel.fields.Where(x => x is IColumnField).Select(x => ((IColumnField)x).ColumnName).ToList <string>(); DataTable table = driver.fetchAll("SELECT ", dbe.Cols(columns), " FROM ", panel.tableName, "WHERE", dbe.Condition(panel.PK)); if (table.Rows.Count > 1) { throw new Exception("PK is not unique"); } if (table.Rows.Count == 0) { throw new WebDriverDataModificationException( "No data fulfill the condition. The record may have been removed."); } DataRow row = table.Rows[0]; panel.OriginalData = table.Rows[0]; foreach (IField field in panel.fields) // fill the fields { if (field is IColumnField) { // value IColumnField cf = (IColumnField)field; cf.Data = row[cf.ColumnName].GetType() != typeof(MySql.Data.Types.MySqlDateTime) ? row[cf.ColumnName] : ((MySql.Data.Types.MySqlDateTime)row[cf.ColumnName]).GetDateTime(); } else { // mapping values are yet to fetch M2NMappingField m2nf = (M2NMappingField)field; m2nf.Data = FetchMappingValues(m2nf.Mapping, (int)panel.PK[0]); } } } foreach (Control c in panel.controls) { if (c is NavTableControl) { AssignDataForNavTable((NavTableControl)c, false); } // always gets the whole table, save in session else if (c is TreeControl && c.data is DataTable) { // there are no data in storedHierarchy - that is only the case of menu in base panel - fill it TreeControl tc = (TreeControl)c; tc.data.DataSet.EnforceConstraints = false; tc.data.Rows.Clear(); HierarchyNavTable hierarchy = (HierarchyNavTable)(tc.data); List <IDbCol> selectCols = new List <IDbCol>(); // don`t need to use constants - the column names are set in HierarchNavTable DataTable fetched = driver.fetchAll("SELECT", dbe.Col(tc.PKColNames[0], "Id"), ",", dbe.Cols(selectCols), dbe.Col(tc.parentColName, "ParentId"), ",", "CAST(", dbe.Col(tc.displayColName), "AS CHAR) AS \"Caption\"", ",", dbe.Col(tc.PKColNames[0], "NavId"), "FROM", panel.tableName); hierarchy.Merge(fetched); tc.data.DataSet.EnforceConstraints = true; } } /* * foreach (Panel p in panel.children) * FillPanel(p); */ }
protected void SaveButton_Click(object sender, EventArgs e) { // extract the data for fields from the table List<IField> fields = new List<IField>(); int i = 1; Dictionary<DataColumn, Dictionary<string, object>> customs = new Dictionary<DataColumn, Dictionary<string, object>>(); foreach (DataColumn col in mm.Stats.ColumnTypes[actPanel.tableName]) { // standard fields TableRow r = tbl.Rows[i++]; if (!((CheckBox)r.Cells[1].Controls[0]).Checked) continue; // label, present, type, valid, caption IColumnFieldFactory factory = factories[Int32.Parse(((DropDownList)r.Cells[2].Controls[0]).SelectedValue)]; // cell 3 is there for FK display column dropList bool required = false; bool unique = false; if(r.Cells[4].Controls.Count == 4){ CheckBox reqChb = (CheckBox)r.Cells[4].Controls[1]; CheckBox uniChb = (CheckBox)r.Cells[4].Controls[3]; required = reqChb.Checked; unique = uniChb.Checked; } string caption = ((TextBox)r.Cells[5].Controls[0]).Text; if (caption == "") caption = null; if (factory is ICustomizableColumnFieldFactory) { customs[col] = new Dictionary<string, object>(); customs[col]["factory"] = factory.Clone(); // so that each field gets its factory even if there more custom fields of the same type customs[col]["required"] = required; customs[col]["unique"] = unique; customs[col]["caption"] = caption; continue; } IField newField; //PBPR // react to the changes to the displaycolumn for the FK if (col.ExtendedProperties.Contains("FK")) { FK colFK = (FK)(col.ExtendedProperties["FK"]); colFK.displayColumn = ((DropDownList)(r.Cells[3].Controls[0])).SelectedValue; col.ExtendedProperties["FK"] = colFK; } newField = factory.Create(col); newField.Caption = caption; newField.Required = required; if (newField is IColumnField) { ((IColumnField)newField).Unique = unique; } fields.Add(newField); } i = 1; foreach (M2NMapping mapping in mappings) { // mappings TableRow r = mappingsTbl.Rows[i++]; // label, present, type (mappingType), valid (req?), caption if (!((CheckBox)r.Cells[1].Controls[0]).Checked) continue; // must be mappingType... List<ValidationRules> rules = new List<ValidationRules>(); // no validation for a mapping mapping.displayColumn = ((DropDownList)(r.Cells[3].Controls[0])).SelectedValue; string caption = ((TextBox)r.Cells[5].Controls[0]).Text; M2NMappingField m2nf = new M2NMappingField(mapping, caption); fields.Add(m2nf); } // crate a control for each checked action List<_min.Models.Control> controls = new List<_min.Models.Control>(); // controls bool valid = true; List<string> errorMsgs = new List<string>(); if (actions.RetrieveStringData().Count == 0) { valid = false; errorMsgs.Add("Choose at least one action for the panel, please."); } foreach (string actionString in actions.RetrieveStringData()) { _min.Models.Control c = new _min.Models.Control(0, actionString, (UserAction)Enum.Parse(typeof(UserAction), actionString)); c.targetPanel = actPanel.controls[0].targetPanel; c.targetPanelId = actPanel.controls[0].targetPanelId; // a miserable way to find out the target panel...really controls.Add(c); } MPanel resPanel = new MPanel(actPanel.tableName, actPanel.panelId, PanelTypes.Editable, new List<MPanel>(), fields, controls, actPanel.PKColNames, null, actPanel.parent); resPanel.panelName = panelName.Text; valid = valid && mm.Architect.checkPanelProposal(resPanel, out errorMsgs, customs); // validate the Panel using Architect`s validator - don`t edit PKs, unique columns must have the constraint, must contain all collumns except Nullable // and AI and more rules validationResult.Items.Clear(); if (valid) { if (customs.Count == 0) { validationResult.Items.Add(new ListItem("Valid")); actPanel = resPanel; mm.SysDriver.BeginTransaction(); mm.SysDriver.UpdatePanel(actPanel); Session.Clear(); mm.SysDriver.IncreaseVersionNumber(); mm.SysDriver.CommitTransaction(); validationResult.Items.Add(new ListItem("Saved")); Response.Redirect(Page.Request.RawUrl); } else { Session["interPanel"] = resPanel; Session["customs"] = customs; Response.RedirectToRoute("ArchitectEditEditableCustomRoute", new {projectName = CE.project.Name, panelId = actPanel.panelId}); // for the sake of unity (and SysDriver) } } else { foreach (string s in errorMsgs) { validationResult.Items.Add(new ListItem(s)); } } }