static void DeleteAllRecursive(this SQLiteConnection conn, IEnumerable elements, bool recursive, ISet <object> objectCache = null) { if (elements == null) { return; } var isRootElement = objectCache == null; objectCache = objectCache ?? new HashSet <object>(); var elementList = elements.Cast <object>().Except(objectCache).ToList(); // Mark the objects for deletion foreach (var element in elementList) { objectCache.Add(element); } if (recursive) { foreach (var element in elementList) { var type = element.GetType(); foreach (var relationshipProperty in type.GetRelationshipProperties()) { var relationshipAttribute = relationshipProperty.GetAttribute <RelationshipAttribute>(); // Ignore read-only attributes or those that are not marked as CascadeDelete if (!relationshipAttribute.IsCascadeDelete || relationshipAttribute.ReadOnly) { continue; } var value = relationshipProperty.GetValue(element, null); conn.DeleteValueRecursive(value, recursive, objectCache); } } } // To improve performance, the root method call will delete all the objects at once if (isRootElement) { conn.DeleteAllObjects(objectCache); } }