I don't know if there is anything more recent about this issue (I searched and couldn't find it) - but after I implemented the suggestion I found that there was a danger of an infinite recursion - and you can guess how I found out.
So I decided to implement some protection against this and came up with the following code. It now appears to work without a problem, but I'd welcome any input about what I might have done wrong implementing the original idea, or any comments about why this might not be a good idea.
public class llbUtil
{
public static bool RecursiveIsDirty(IEntity argEntity)
{
List<IEntityCollection> visitedCollections = new List<IEntityCollection>();
List<IEntity> visitedEntities = new List<IEntity>();
return RecursiveIsDirty(argEntity, visitedCollections, visitedEntities);
}
private static bool RecursiveIsDirty(IEntity argEntity, List<IEntityCollection> visitedCollections, List<IEntity> visitedEntities)
{
//Prevent infinite recursion
if (visitedEntities.Contains(argEntity))
{
return false;
}
else
{
visitedEntities.Add(argEntity);
}
//Answer from Otis in LLBLgen forum
//
//Well, you can traverse the entities referenced by an entity, like the Save routine does too, by using the following routines:
//- entity.GetDependentRelatedEntities(), which gets a collection of entity objects which 'entity' depends on
// (e.g. a loaded Customer entity for an order entity). m:1/1:1 relations
//- entity.GetDependingRelatedEntities(), which gets a collection of entity objects which depend on 'entity'. (1:1 relations)
//- entity.GetMemberEntityCollections(), which gets a collection of collections (1:n relations).
// See the reference manual for details on these methods. With the contents of these methods you can check further,
// for example recursively in there to go deeper into the graph.
//Entity Dirty?
if (argEntity.IsDirty) return true;
//- entity.GetDependentRelatedEntities(), which gets a collection of entity objects which 'entity' depends on
foreach (IEntity entity in argEntity.GetDependentRelatedEntities())
{
if (entity != null)
{
if (RecursiveIsDirty(entity,visitedCollections, visitedEntities))
{
return true;
}
}
}
//- entity.GetDependingRelatedEntities(), which gets a collection of entity objects which depend on 'entity'. (1:1 relations)
foreach (IEntity entity in argEntity.GetDependingRelatedEntities())
{
if (entity != null)
{
if (RecursiveIsDirty(entity, visitedCollections, visitedEntities))
{
return true;
}
}
}
//- entity.GetMemberEntityCollections(), which gets a collection of collections (1:n relations).
foreach (IEntityCollection entityCollection in argEntity.GetMemberEntityCollections())
{
if (entityCollection != null)
{
if (RecursiveIsDirty(entityCollection, visitedCollections, visitedEntities))
{
return true;
}
}
}
return false;
}
public static bool RecursiveIsDirty(IEntityCollection argCollection)
{
List<IEntityCollection> visitedCollections = new List<IEntityCollection>();
List<IEntity> visitedEntities = new List<IEntity>();
return RecursiveIsDirty(argCollection, visitedCollections, visitedEntities);
}
private static bool RecursiveIsDirty(IEntityCollection argCollection, List<IEntityCollection> visitedCollections, List<IEntity> visitedEntities)
{
//Prevent infinite recursion
if (visitedCollections.Contains(argCollection))
{
return false;
}
else
{
visitedCollections.Add(argCollection);
}
//default RecursiveIsDirtyMode.RecursiveChildrenAndSiblings
//Check for Entities in DeleteTracker
if (argCollection.RemovedEntitiesTracker != null)
{
if (argCollection.RemovedEntitiesTracker.Count > 0)
return true;
}
//Loop through Collection
foreach (IEntity myEntity in argCollection)
{
if (myEntity != null)
{
if (RecursiveIsDirty(myEntity, visitedCollections, visitedEntities))
return true;
}
}
return false;
}
}