Reputation: 18869
I have this table in my SQL database:
Folders
-----------
FolderID
Name
ParentFolderID
I have a foreign-key relationship between ParentFolderID
and FolderID
so that it creates a parent/child relationship.
When I delete a folder, I'd like it to delete all child folders as well. I couldn't set the relationship to have a cascade delete because apparently SQL Server doesn't allow that on a relationship like this. But I'm using Entity Framework to create my classes based on these tables, so I plan on just doing it in my code.
I tried doing this with just a recursive method:
protected void DeleteUserFolder(UserFolder userFolder)
{
if (userFolder.ChildFolders.Count.Equals(0))
{
_entities.UserFolders.Remove(userFolder);
_entities.SaveChanges();
}
else
{
foreach (UserFolder childFolder in userFolder.ChildFolders.ToList())
{
DeleteUserFolder(childFolder);
}
}
}
It's not working as expected though, it only deletes about half my folders.
For instance, I had one parent folder named Test. Test had two child folders, Test2 and Test3. Test2 also had two child folders. I tried to delete Test, but it only deleted Test3 and the child folders in Test2.
Am I doing something wrong in this code? Or is there a better way to do this?
Upvotes: 1
Views: 971
Reputation: 203814
We can actually create a generic method that can fully traverse any tree based structure easily enough:
public static IEnumerable<T> Traverse<T>(T item,
Func<T, IEnumerable<T>> childSelector)
{
var stack = new Stack<T>();
stack.Push(item);
while (stack.Any())
{
var next = stack.Pop();
yield return next;
foreach (var child in childSelector(next))
stack.Push(child);
}
}
Now we can just call that using your data:
foreach(var folder in Traverse(userFolder, f => f.ChildFolders))
_entities.UserFolders.Remove(folder);
_entities.SaveChanges();
Upvotes: 1