B2016-130: Copy and paste replace steps causing missing and duplicate items in tree (problems with ‘NextItems’)

This commit is contained in:
2017-08-07 13:05:02 +00:00
parent e8ae40ef7f
commit 20a07c6a3e
12 changed files with 135 additions and 31 deletions

View File

@@ -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)

View File

@@ -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;