I have a grid with the datasource set to an EntitySpaces collection, with a checkbox column. When the checkbox is checked, I want to create a record and when it is cleared I want to delete the same record.
To avoid the obvious PK violation save if a user repeatedly checks and unchecks an item, I am trying to retrieve the previously deleted entities and mark them as not deleted. However, when I use CombineDeletedEntities
and SeparateDeletedEntities
on the collection it creates duplicate entries in the collection.
roleFunctions.CombineDeletedEntities();
// On third cycle through, this is the error line
RoleFunction foundItem = roleFunctions.FindByPrimaryKey(roleName, functionName);
if (foundItem != null)
{
foundItem.RowState = esDataRowState.Unchanged;
// Extraneous logic...
}
else
{
// Create new item...
}
roleFunctions.SeparateDeletedEntities();
So basically when I do FindByPrimaryKey
the third time, EntitySpaces has created an extra item somehow which causes an InvalidOperationException
with a message of Sequence contains more than one matching element
.
Has anyone hit this with EntitySpaces before and how did you end up nicely handling a user creating and deleting the same entity multiple times in a single session?
This was a fairly easy fix, especially since EntitySpaces is open source. The two methods I was using to avoid creating duplicate records are shown below:
public override void CombineDeletedEntities()
{
if (this.deletedEntities != null && this.deletedEntities.Count > 0)
{
foreach (T entity in deletedEntities)
{
entities.Add(entity);
}
}
}
public override void SeparateDeletedEntities()
{
foreach (T entity in this.entities)
{
if (entity.rowState == esDataRowState.Deleted)
{
if (deletedEntities == null)
{
deletedEntities = new BindingList<T>();
}
deletedEntities.Add(entity);
}
}
if (this.deletedEntities != null && this.deletedEntities.Count > 0)
{
foreach (T entity in deletedEntities)
{
entities.Remove(entity);
}
}
}
Looking at the above it becomes fairly obvious that the code will continue adding back the same entities into the deletedEntities
list every time we call SeparateDeletedEntities
.
The easy solution was to clear the deletedEntities
collection when the are combined with the collection proper:
public override void CombineDeletedEntities()
{
if (this.deletedEntities != null && this.deletedEntities.Count > 0)
{
foreach (T entity in deletedEntities)
{
entities.Add(entity);
}
this.deletedEntities.Clear();
}
}
The downside to this quick and dirty fix is that you probably don't want to call collection.Save()
after calling CombineDeletedEntities
until you have called SeparateDeletedEntities
, since having an empty deletedEntities
collection will probably cause your save to skip all deletes.
I would have liked to just add a if (!deletedEntities.Contains(entity))
call in the SeparateDeletedEntities
routine, but the equality comparison sees the entities as different so I went with the simpler solution.