B2016-130: Copy and paste replace steps causing missing and duplicate items in tree (problems with ‘NextItems’)
This commit is contained in:
@@ -142,7 +142,7 @@ namespace VEPROMS.CSLA.Library
|
||||
sb.Append(Counts<Membership>(Membership.CountNotDisposed, Membership.CountNotFinalized));
|
||||
sb.Append(Counts<MembershipInfo>(MembershipInfo.CountNotDisposed, MembershipInfo.CountNotFinalized));
|
||||
sb.Append(Counts<MembershipInfoList>(MembershipInfoList.CountNotDisposed, MembershipInfoList.CountNotFinalized));
|
||||
sb.Append(Counts<NextItems>(NextItems.CountNotDisposed, NextItems.CountNotFinalized));
|
||||
//sb.Append(Counts<NextItems>(NextItems.CountNotDisposed, NextItems.CountNotFinalized));
|
||||
sb.Append(Counts<Part>(Part.CountNotDisposed, Part.CountNotFinalized));
|
||||
sb.Append(Counts<PartAudit>(PartAudit.CountNotDisposed, PartAudit.CountNotFinalized));
|
||||
sb.Append(Counts<PartAuditInfo>(PartAuditInfo.CountNotDisposed, PartAuditInfo.CountNotFinalized));
|
||||
@@ -353,7 +353,7 @@ namespace VEPROMS.CSLA.Library
|
||||
sb.Append(Counts<Membership>(Membership.CountCreated, Membership.CountNotDisposed, Membership.CountNotFinalized));
|
||||
sb.Append(Counts<MembershipInfo>(MembershipInfo.CountCreated, MembershipInfo.CountNotDisposed, MembershipInfo.CountNotFinalized));
|
||||
sb.Append(Counts<MembershipInfoList>(MembershipInfoList.CountCreated, MembershipInfoList.CountNotDisposed, MembershipInfoList.CountNotFinalized));
|
||||
sb.Append(Counts<NextItems>(NextItems.CountCreated, NextItems.CountNotDisposed, NextItems.CountNotFinalized));
|
||||
//sb.Append(Counts<NextItems>(NextItems.CountCreated, NextItems.CountNotDisposed, NextItems.CountNotFinalized));
|
||||
sb.Append(Counts<Part>(Part.CountCreated, Part.CountNotDisposed, Part.CountNotFinalized));
|
||||
sb.Append(Counts<PartAudit>(PartAudit.CountCreated, PartAudit.CountNotDisposed, PartAudit.CountNotFinalized));
|
||||
sb.Append(Counts<PartAuditInfo>(PartAuditInfo.CountCreated, PartAuditInfo.CountNotDisposed, PartAuditInfo.CountNotFinalized));
|
||||
|
@@ -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)
|
||||
|
@@ -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));
|
||||
}
|
||||
|
@@ -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<ItemInfo>(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;
|
||||
/// <summary>
|
||||
/// 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<ItemInfo>(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)
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user