Удалить сущность с саморегулирующимся внешним ключом с помощью рекурсивной функции в Entity Framework

Я разрабатываю проект ASP.NET MVC с использованием Entity Framework. Я использую подход «сначала код». У меня возникла проблема с удалением объекта с саморегулирующимся внешним ключом и связанных с ним объектов с использованием рекурсивной функции.

Я удаляю с помощью рекурсивной функции, потому что в SQL Server невозможно установить каскад удаления для внешнего ключа, ссылающегося на себя. Когда я удаляю, возникает исключение переполнения стека, если у объекта есть связанные объекты, которые нужно удалить. Потому что рекурсивная функция никогда не перестает вызывать. Это стало бесконечным.

Это мой класс сущности с FK, ссылающимся на себя.

public class Category
{
        public int Id { get; set; }
        [Required]
        [MaxLength(50)]
        public string Name { get; set; }
        [MaxLength(55)]
        public string MmName { get; set; }
        public int? ParentId { get; set; }

        [ForeignKey("ParentId")]
        public virtual Category ParentCategory { get; set; }
        public virtual ICollection<Category> Categories { get; set; }
        public virtual ICollection<Item> Items { get; set; }
}

Вот как я удаляю в модели с помощью рекурсивной функции:

public List<int> deletedIds = new List<int>();

        public Category Delete(Category category)
        {
            if(category!=null)
            {
                int intentionId = category.Id;
                if(category.Categories!=null && category.Categories.Count>0)
                {
                    RelatedCategories(category.Categories);
                }
                deletedIds.Add(intentionId);
                if(deletedIds.Count>0)
                {
                    IEnumerable<Category> categories = context.Categories.Where(x => deletedIds.Contains(x.Id));
                    if(categories!=null && categories.Count()>0)
                    {
                        context.Categories.RemoveRange(categories);
                        context.SaveChanges();
                    }
                }
            }
            return category;
        }

        private void RelatedCategories(IEnumerable<Category> categories)
        {
            foreach(var c in categories)
            {
                deletedIds.Add(c.Id);
                while (c.Categories!=null && c.Categories.Count > 0)
                {
                    RelatedCategories(c.Categories);
                }
            }        
        }

Я удаляю данные в этой структуре

введите описание изображения здесь

Я удаляю test1. Но когда рекурсивная функция вызывается сама по себе, она просто постоянно передает List с помощью test2. Как я могу исправить свой код? Как я могу удалить категорию и связанные с ней категории с помощью рекурсивной функции?

Я пробовал это, чтобы остановить рекурсию. Это просто невозможно остановить и все равно.

private void RelatedCategories(IEnumerable<Category> categories)
        {
            Category repeatedCategory = null;
            if(categories!=null && categories.Count()>0 && deletedIds.Count>0)
            {
                repeatedCategory = categories.FirstOrDefault(x => deletedIds.Contains(categories.Select(c => c.Id).FirstOrDefault()));
            }
            if(repeatedCategory!=null)
            {
                return;
            }
            foreach(var c in categories)
            {
                deletedIds.Add(c.Id);
                while (c.Categories!=null && c.Categories.Count > 0)
                {
                    RelatedCategories(c.Categories);
                }
            }        
        }

person Wai Yan Hein    schedule 02.07.2016    source источник
comment
Я обнаружил ошибку и скоро отправлю ответ.   -  person Wai Yan Hein    schedule 02.07.2016


Ответы (1)


Я нашел ошибку. Я виноват в рекурсии. Я использовал цикл while в рекурсивной функции. Так получился бесконечный цикл. На самом деле мне нужно было использовать оператор if. Я просто заменил эту функцию. Все работало нормально.

private void RelatedCategories(IEnumerable<Category> categories)
        {
            foreach (var c in categories)
            {
                deletedIds.Add(c.Id);
                if(c.Categories!=null && c.Categories.Any())
                {
                    SetRelatedCategories(c.Categories);
                }
            }
        }
person Wai Yan Hein    schedule 03.07.2016