From 20a07c6a3e9abb8fc60a7130fbdbcf8749ee99ae Mon Sep 17 00:00:00 2001 From: Kathy Date: Mon, 7 Aug 2017 13:05:02 +0000 Subject: [PATCH] =?UTF-8?q?B2016-130:=20Copy=20and=20paste=20replace=20ste?= =?UTF-8?q?ps=20causing=20missing=20and=20duplicate=20items=20in=20tree=20?= =?UTF-8?q?(problems=20with=20=E2=80=98NextItems=E2=80=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extension/CacheUsage.cs | 4 +- .../VEPROMS.CSLA.Library/Extension/ItemExt.cs | 13 +-- .../Extension/ItemInsertExt.cs | 10 +-- .../Generated/ItemInfo.cs | 89 +++++++++++++++++++ .../Generated/ItemInfoList.cs | 10 +++ .../DisplayFoldoutMaint.cs | 2 +- PROMS/Volian.Controls.Library/DisplayTags.cs | 2 +- .../DisplayTransition.cs | 6 +- PROMS/Volian.Controls.Library/EditItem.cs | 2 +- PROMS/Volian.Controls.Library/StepPanel.cs | 8 +- PROMS/Volian.Print.Library/Pagination.cs | 2 +- PROMS/Volian.Print.Library/vlnParagraph.cs | 18 ++-- 12 files changed, 135 insertions(+), 31 deletions(-) diff --git a/PROMS/VEPROMS.CSLA.Library/Extension/CacheUsage.cs b/PROMS/VEPROMS.CSLA.Library/Extension/CacheUsage.cs index f2f838e0..6add287d 100644 --- a/PROMS/VEPROMS.CSLA.Library/Extension/CacheUsage.cs +++ b/PROMS/VEPROMS.CSLA.Library/Extension/CacheUsage.cs @@ -142,7 +142,7 @@ namespace VEPROMS.CSLA.Library sb.Append(Counts(Membership.CountNotDisposed, Membership.CountNotFinalized)); sb.Append(Counts(MembershipInfo.CountNotDisposed, MembershipInfo.CountNotFinalized)); sb.Append(Counts(MembershipInfoList.CountNotDisposed, MembershipInfoList.CountNotFinalized)); - sb.Append(Counts(NextItems.CountNotDisposed, NextItems.CountNotFinalized)); + //sb.Append(Counts(NextItems.CountNotDisposed, NextItems.CountNotFinalized)); sb.Append(Counts(Part.CountNotDisposed, Part.CountNotFinalized)); sb.Append(Counts(PartAudit.CountNotDisposed, PartAudit.CountNotFinalized)); sb.Append(Counts(PartAuditInfo.CountNotDisposed, PartAuditInfo.CountNotFinalized)); @@ -353,7 +353,7 @@ namespace VEPROMS.CSLA.Library sb.Append(Counts(Membership.CountCreated, Membership.CountNotDisposed, Membership.CountNotFinalized)); sb.Append(Counts(MembershipInfo.CountCreated, MembershipInfo.CountNotDisposed, MembershipInfo.CountNotFinalized)); sb.Append(Counts(MembershipInfoList.CountCreated, MembershipInfoList.CountNotDisposed, MembershipInfoList.CountNotFinalized)); - sb.Append(Counts(NextItems.CountCreated, NextItems.CountNotDisposed, NextItems.CountNotFinalized)); + //sb.Append(Counts(NextItems.CountCreated, NextItems.CountNotDisposed, NextItems.CountNotFinalized)); sb.Append(Counts(Part.CountCreated, Part.CountNotDisposed, Part.CountNotFinalized)); sb.Append(Counts(PartAudit.CountCreated, PartAudit.CountNotDisposed, PartAudit.CountNotFinalized)); sb.Append(Counts(PartAuditInfo.CountCreated, PartAuditInfo.CountNotDisposed, PartAuditInfo.CountNotFinalized)); diff --git a/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs b/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs index 72df662b..da6b8130 100644 --- a/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs +++ b/PROMS/VEPROMS.CSLA.Library/Extension/ItemExt.cs @@ -254,9 +254,7 @@ namespace VEPROMS.CSLA.Library { using (Item fromitem = previousInfo == null ? null : previousInfo.Get()) { - ItemInfo nextInfo = null; // Check to see if the item is being inserted in the middle of some items. - if (previousInfo != null && previousInfo.NextItems != null && previousInfo.NextItems.Count > 0) - nextInfo = previousInfo.NextItems[0]; + ItemInfo nextInfo = previousInfo.GetNext(); // Check to see if the item is being inserted in the middle of some items. using (Item itm = Item.MakeItem(fromitem, cont)) { newitemid = itm.ItemID; @@ -1986,8 +1984,13 @@ namespace VEPROMS.CSLA.Library get { ItemInfo temp = this; - while (temp.NextItems != null && temp.NextItems.Count > 0) temp = temp.NextItems[0]; - return temp; + ItemInfo last = this; + while (temp != null) + { + last = temp; + temp = temp.GetNext(); + } + return last; } } public ItemInfo LastChild(E_FromType partType) diff --git a/PROMS/VEPROMS.CSLA.Library/Extension/ItemInsertExt.cs b/PROMS/VEPROMS.CSLA.Library/Extension/ItemInsertExt.cs index 4cbddcc4..ad9630b4 100644 --- a/PROMS/VEPROMS.CSLA.Library/Extension/ItemInsertExt.cs +++ b/PROMS/VEPROMS.CSLA.Library/Extension/ItemInsertExt.cs @@ -2056,9 +2056,7 @@ namespace VEPROMS.CSLA.Library get { if (PrintAllAtOnce) return GetNextItem(); - if (NextItemCount > 0 && NextItems != null && NextItems.Count > 0) - return NextItems[0]; - return null; + return GetNext(); } } private static void ResetOrdinal(int itemID) @@ -2335,16 +2333,16 @@ namespace VEPROMS.CSLA.Library newItemInfo.UpdateROText(); newItemInfo.UpdatePastedStepTransitionText(); // Add to tree - if (newItemInfo.NextItemCount > 0) + if (newItemInfo.NextItem != null) { - using (ItemInfo itm = ItemInfo.Get(newItemInfo.NextItem.ItemID)) + using (ItemInfo itm = ItemInfo.GetNonCached(newItemInfo.NextItem.ItemID)) { itm.OnNewSiblingBefore(new ItemInfoInsertEventArgs(newItemInfo, ItemInfo.EAddpingPart.Before)); } } else if (newItemInfo.PreviousID != null) { - using (ItemInfo itm2 = ItemInfo.Get((int)newItemInfo.PreviousID)) + using (ItemInfo itm2 = ItemInfo.GetNonCached((int)newItemInfo.PreviousID)) { itm2.OnNewSiblingAfter(new ItemInfoInsertEventArgs(newItemInfo, ItemInfo.EAddpingPart.After)); } diff --git a/PROMS/VEPROMS.CSLA.Library/Generated/ItemInfo.cs b/PROMS/VEPROMS.CSLA.Library/Generated/ItemInfo.cs index 705749f4..79b7fc92 100644 --- a/PROMS/VEPROMS.CSLA.Library/Generated/ItemInfo.cs +++ b/PROMS/VEPROMS.CSLA.Library/Generated/ItemInfo.cs @@ -264,6 +264,76 @@ namespace VEPROMS.CSLA.Library foreach (ItemInfo tmp in _CacheByPrimaryKey[_ItemID.ToString()]) tmp._ItemDocVersionCount = -1; // This will cause the data to be requeried } + // B2016-130: GetNext was added so that NextItems was not used for finding the next item in a list of iteminfos using 'nextitems'. + // When using 'nextitems' internal list data structures for items were not maintained consistently with the database items during + // some occurrences of copy/paste/delete. + [Serializable()] + private class PreviousIDCriteria + { + public PreviousIDCriteria(int? previousID) + { + _PreviousID = previousID; + } + private int? _PreviousID; + public int? PreviousID + { + get { return _PreviousID; } + set { _PreviousID = value; } + } + } + public ItemInfo GetNext() + { + try + { + ItemInfo tmp = DataPortal.Fetch(new PreviousIDCriteria(ItemID)); + if (tmp.ErrorMessage == "No Record Found") + { + tmp.Dispose(); // Clean-up ItemInfo + tmp = null; + } + return tmp; + } + catch (Exception ex) + { + throw new DbCslaException("Error on ItemInfo.GetNext", ex); + } + } + private void DataPortal_Fetch(PreviousIDCriteria criteria) + { + if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] ItemInfo.DataPortal_FetchPreviousID", GetHashCode()); + try + { + using (SqlConnection cn = Database.VEPROMS_SqlConnection) + { + ApplicationContext.LocalContext["cn"] = cn; + using (SqlCommand cm = cn.CreateCommand()) + { + cm.CommandType = CommandType.StoredProcedure; + cm.CommandText = "getNextItems"; + cm.Parameters.AddWithValue("@PreviousID", criteria.PreviousID); + cm.CommandTimeout = Database.DefaultTimeout; + using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader())) + { + if (!dr.Read()) + { + _ErrorMessage = "No Record Found"; + return; + } + ReadData(dr); + } + } + // removing of item only needed for local data portal + if (ApplicationContext.ExecutionLocation == ApplicationContext.ExecutionLocations.Client) + ApplicationContext.LocalContext.Remove("cn"); + } + } + catch (Exception ex) + { + if (_MyLog.IsErrorEnabled) _MyLog.Error("ItemInfo.DataPortal_FetchPreviousID", ex); + _ErrorMessage = ex.Message; + throw new DbCslaException("ItemInfo.DataPortal_Fetch", ex); + } + } private int _NextItemCount = 0; /// /// Count of NextItems for this Item @@ -578,6 +648,25 @@ namespace VEPROMS.CSLA.Library throw new DbCslaException("Error on ItemInfo.Get", ex); } } + // B2016-130: Just get an item from the database, but don't add it to the cache because it gets + // freed (only use this in a 'using' statement). + public static ItemInfo GetNonCached(int itemID) + { + try + { + ItemInfo tmp = DataPortal.Fetch(new PKCriteria(itemID)); + if (tmp.ErrorMessage == "No Record Found") + { + tmp.Dispose(); // Clean-up ItemInfo + tmp = null; + } + return tmp; + } + catch (Exception ex) + { + throw new DbCslaException("Error on ItemInfo.GetNonCached", ex); + } + } #endregion #region Data Access Portal internal ItemInfo(SafeDataReader dr) diff --git a/PROMS/VEPROMS.CSLA.Library/Generated/ItemInfoList.cs b/PROMS/VEPROMS.CSLA.Library/Generated/ItemInfoList.cs index d2e303d7..cef2920f 100644 --- a/PROMS/VEPROMS.CSLA.Library/Generated/ItemInfoList.cs +++ b/PROMS/VEPROMS.CSLA.Library/Generated/ItemInfoList.cs @@ -64,7 +64,17 @@ namespace VEPROMS.CSLA.Library for (int i = 0; i < Count; i++) { if (base[i] == sender) + { + // Added insert to fix when item is replaced and a 'delete' is done, the item needs inserted. Note + // that when text is modified, i.e. 'Changed', this code is not executed. Fixed B2016-130. + RefreshingList = true; + IsReadOnly = false; + Items.Insert(i, (sender as ItemInfo).MyPrevious); + IsReadOnly = true; this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, i)); + RefreshingList = false; + break; + } } } private bool _Disposed = false; diff --git a/PROMS/Volian.Controls.Library/DisplayFoldoutMaint.cs b/PROMS/Volian.Controls.Library/DisplayFoldoutMaint.cs index e9aeb26b..cc9a5d23 100644 --- a/PROMS/Volian.Controls.Library/DisplayFoldoutMaint.cs +++ b/PROMS/Volian.Controls.Library/DisplayFoldoutMaint.cs @@ -91,7 +91,7 @@ namespace Volian.Controls.Library } else lstCBSteps.Items.Add(startitm, CheckState.Unchecked); - startitm = (startitm.NextItem != null && startitm.NextItems.Count > 0 ? startitm.NextItems[0] : null); + startitm = startitm.GetNext(); } } private void listBoxFoldouts_SelectedIndexChanged(object sender, EventArgs e) diff --git a/PROMS/Volian.Controls.Library/DisplayTags.cs b/PROMS/Volian.Controls.Library/DisplayTags.cs index f1bb10b4..8681c5e9 100644 --- a/PROMS/Volian.Controls.Library/DisplayTags.cs +++ b/PROMS/Volian.Controls.Library/DisplayTags.cs @@ -520,7 +520,7 @@ namespace Volian.Controls.Library // itm.UserID = Volian.Base.Library.VlnSettings.UserID; // itm.Save(); //} - startitm = (startitm.NextItem != null && startitm.NextItems.Count > 0 ? startitm.NextItems[0] : null); + startitm = startitm.GetNext(); } msgBox = string.Format("All Step Types at this level were changed to {0}", listBoxStepTypes.Items[listBoxStepTypes.SelectedIndex]); } diff --git a/PROMS/Volian.Controls.Library/DisplayTransition.cs b/PROMS/Volian.Controls.Library/DisplayTransition.cs index e8e21af9..7a463fc5 100644 --- a/PROMS/Volian.Controls.Library/DisplayTransition.cs +++ b/PROMS/Volian.Controls.Library/DisplayTransition.cs @@ -513,7 +513,7 @@ namespace Volian.Controls.Library tvTran.SelectedNode = tvTran.Nodes[active]; setsel = true; } - startitm = (startitm.NextItem != null && startitm.NextItems.Count > 0 ? startitm.NextItems[0] : null); + startitm = startitm.GetNext(); } if (!setsel) tvTran.SelectedNode = tvTran.Nodes[0]; tvTran.BeforeExpand += new TreeViewCancelEventHandler(tvTran_BeforeExpand); @@ -544,7 +544,7 @@ namespace Volian.Controls.Library if (secitm.ItemID == secstart) cbTranSects.SelectedIndex = active; } if (secitm.Sections != null && secitm.Sections.Count > 0) cbTranSectsFillIn(secitm.Sections[0], secstart, false); - secitm = (secitm.NextItem != null && secitm.NextItems.Count > 0 ? secitm.NextItems[0] : null); + secitm = secitm.GetNext(); } if (cbTranSects.SelectedIndex == -1) cbTranSects.SelectedIndex = 0; cbTranSects.Refresh(); @@ -562,7 +562,7 @@ namespace Volian.Controls.Library int active = cbTranProcs.Items.Add(prcitm); if (_CurrentProcedure.ContentID == prcitm.MyContent.ContentID) _CurrentProcIndex = active; if (prcitm.MyContent.ContentID == selitm.MyContent.ContentID) cbTranProcs.SelectedIndex = active; - prcitm = (prcitm.NextItem != null && prcitm.NextItems.Count > 0 ? prcitm.NextItems[0] : null); + prcitm = prcitm.GetNext(); } } private void SetControlsEnabling() diff --git a/PROMS/Volian.Controls.Library/EditItem.cs b/PROMS/Volian.Controls.Library/EditItem.cs index c5cbb9e0..2230f54a 100644 --- a/PROMS/Volian.Controls.Library/EditItem.cs +++ b/PROMS/Volian.Controls.Library/EditItem.cs @@ -3393,7 +3393,7 @@ namespace Volian.Controls.Library } } // if on a caution or note check the step below me, which is really my activeparent (cautions/notes are above their respective parent) - if ((itm.IsCaution || itm.IsNote) && (itm.NextItem == null || itm.NextItemCount == 0) && (itm.ActiveParent as ItemInfo).SupInfos != null && (itm.ActiveParent as ItemInfo).SupInfos.Count > 0) + if ((itm.IsCaution || itm.IsNote) && itm.NextItem == null && (itm.ActiveParent as ItemInfo).SupInfos != null && (itm.ActiveParent as ItemInfo).SupInfos.Count > 0) return GetEditItemFromItemID((itm.ActiveParent as ItemInfo).ItemID); // Finally check substeps: diff --git a/PROMS/Volian.Controls.Library/StepPanel.cs b/PROMS/Volian.Controls.Library/StepPanel.cs index 4bb45f09..ccb0ef90 100644 --- a/PROMS/Volian.Controls.Library/StepPanel.cs +++ b/PROMS/Volian.Controls.Library/StepPanel.cs @@ -949,7 +949,8 @@ namespace Volian.Controls.Library { if (lookAtSub && ii.Sections != null) return TopPart(ii.Sections[0]); if (lookAtSub && ii.Steps != null) return TopPart(ii.Steps[0]); - if (ii.IsSection && ii.NextItems != null && ii.NextItems.Count > 0) return TopPart(ii.NextItems[0]); + ItemInfo nxt = ii.GetNext(); + if (nxt != null) return TopPart(nxt); } else { @@ -972,7 +973,8 @@ namespace Volian.Controls.Library if (lookAtRNO && ii.RNOs != null && ii.RNOLevel >= ii.ColumnMode) return TopPart(ii.RNOs[0]); // Nextsibling - go to top part of sibling // TODO: RHM - NextItems was not null when it should have been after delete of a note below a caution - if (ii.NextItems != null && ii.NextItems.Count > 0) return TopPart(ii.NextItems[0]); + ItemInfo nxt = ii.GetNext(); + if (nxt != null) return TopPart(nxt); // If on caution, if parent has note - go to note if (ii.IsCautionPart && ii.MyParent.Notes != null) return ii.MyParent.Notes[0]; // If on caution, if parent !has note or if on note go to parent @@ -1001,7 +1003,7 @@ namespace Volian.Controls.Library ii = ii.LastSibling; break; case Keys.PageDown: - ii = ii.NextItems != null && ii.NextItems.Count > 0 ? ii.NextItems[0] : null; + ii = ii.GetNext(); break; case Keys.PageUp: ii = ii.MyPrevious; diff --git a/PROMS/Volian.Print.Library/Pagination.cs b/PROMS/Volian.Print.Library/Pagination.cs index 3f4bfcfa..8ef05b02 100644 --- a/PROMS/Volian.Print.Library/Pagination.cs +++ b/PROMS/Volian.Print.Library/Pagination.cs @@ -375,7 +375,7 @@ namespace Volian.Print.Library mySize += (2*SixLinesPerInch); // mySize is the size of this step and includes an extra blank line. For HLS, if this is the last step in section & there is room in footer to keep // step on the page, do so by eliminating the blank line before doing the test to see if it fits. - if (MyItemInfo.IsHigh && mySize >= (2 * SixLinesPerInch) && MyItemInfo.MyDocStyle.Layout.FooterLength > 0 && (MyItemInfo.MyDocStyle.End.Message == null || MyItemInfo.MyDocStyle.End.Message == "") && MyItemInfo.NextItemCount == 0 && (MyItemInfo.Steps == null || MyItemInfo.Steps.Count == 0) && (MyItemInfo.RNOs == null || MyItemInfo.RNOs.Count == 0)) + if (MyItemInfo.IsHigh && mySize >= (2 * SixLinesPerInch) && MyItemInfo.MyDocStyle.Layout.FooterLength > 0 && (MyItemInfo.MyDocStyle.End.Message == null || MyItemInfo.MyDocStyle.End.Message == "") && MyItemInfo.NextItem != null && (MyItemInfo.Steps == null || MyItemInfo.Steps.Count == 0) && (MyItemInfo.RNOs == null || MyItemInfo.RNOs.Count == 0)) mySize -= SixLinesPerInch; //// Account for extra lines in the end message (flag < 0) float adjMsgY = 0; diff --git a/PROMS/Volian.Print.Library/vlnParagraph.cs b/PROMS/Volian.Print.Library/vlnParagraph.cs index 712b2504..e42228cc 100644 --- a/PROMS/Volian.Print.Library/vlnParagraph.cs +++ b/PROMS/Volian.Print.Library/vlnParagraph.cs @@ -153,7 +153,7 @@ namespace Volian.Print.Library { if ((childItemInfo.IsCaution || childItemInfo.IsNote) && childItemInfo.MyPrevious != null && childItemInfo.MyPrevious.MyContent.Type != childItemInfo.MyContent.Type && - childItemInfo.NextItemCount > 0 && childItemInfo.NextItem!= null && childItemInfo.MyContent.Type == childItemInfo.NextItem.MyContent.Type) + childItemInfo.NextItem != null && childItemInfo.MyContent.Type == childItemInfo.NextItem.MyContent.Type) childItemInfo.SetupTags(); // added for V.C. Summer Transition caution in EOP-15.0 step 5.4 if (lastHeader != null) { @@ -372,7 +372,7 @@ namespace Volian.Print.Library if (nxt != null && (nxt.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS) nxtIsBoxed = 0; yoff += (nxtIsBoxed * vlnPrintObject.SixLinesPerInch); } - if (childItemInfo.IsSequential && childItemInfo.NextItemCount > 0 && childItemInfo.MyParent.IsHigh && ((childItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.XBlankW1stLevSub) == E_DocStructStyle.XBlankW1stLevSub)) + if (childItemInfo.IsSequential && childItemInfo.NextItem != null && childItemInfo.MyParent.IsHigh && ((childItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.XBlankW1stLevSub) == E_DocStructStyle.XBlankW1stLevSub)) yoff += vlnPrintObject.SixLinesPerInch; boxHLS = false; lastChild = childItemInfo; @@ -811,7 +811,7 @@ namespace Volian.Print.Library { // This section of code draws the lines around the substeps (the actual table part) Paragraph horzLine = new Paragraph(ii.ActiveFormat.PlantFormat.FormatData.BoxList[0].BXHorz, iSymblFont); - bool bottomOfTable = (ii.NextItem == null || ii.NextItemCount == 0) || + bool bottomOfTable = ii.NextItem == null || (MyPageHelper.ParaBreaks.Count > 0 && MyPageHelper.ParaBreaks[0].MyItemInfo.ItemID == ii.NextItem.ItemID); // if bottom of table use different cross/beg/end chars than if in middle of table. Paragraph leftLine = new Paragraph(bottomOfTable ? bx.BXLLC : bx.BXMLS, iSymblFont); @@ -857,7 +857,7 @@ namespace Volian.Print.Library // Now handle middle parts of the table. For whatever sub level we're at, draw the cross character // and the horizontal. This is case where the component number may have multiple descriptions,positions, etc. associated // with it. - if (!ii.MyParent.IsHigh && ii.NextItem != null && ii.NextItemCount > 0) + if (!ii.MyParent.IsHigh && ii.NextItem != null) { // draw horizontally from this sublevel to the end. int sublev = 0; @@ -2283,15 +2283,17 @@ namespace Volian.Print.Library // Go to the parent, and find its next and check if it or any of its substeps or next steps or any of their substeps have supinfo, // and if so, return the id. ItemInfo par = ii.MyParent; - if (!par.IsSection && par.NextItems != null && par.NextItems.Count > 0) + ItemInfo parsnxt = par.GetNext(); + if (!par.IsSection && parsnxt != null) { - par = par.NextItem; + par = parsnxt; while (par != null && !par.IsSection) { id = GetIdThatHasSupInfoItemsSibNext(par, startid); if (id != -1) return id; par = par.MyParent; - if (!par.IsSection && par.NextItems != null && par.NextItems.Count > 0) par = par.NextItem; + ItemInfo sparsnxt = par.GetNext(); + if (!par.IsSection && sparsnxt != null) par = sparsnxt; else return -1; } } @@ -2303,7 +2305,7 @@ namespace Volian.Print.Library int id = -1; while (ii != null) { - SectionInfo supInfoSect = ii.MyActiveSection as SectionInfo; + SectionInfo supInfoSect = ii.ActiveSection as SectionInfo; // if there is a pagebreak on this step section step, quit looking for supinfos. The // break has to occur here. if (supInfoSect.StepSectPageBreaks.Contains(ii.ItemID)) return -1;