简体   繁体   中英

delete records from related multiple EF tables

I tried handle the cascading deletes manually deleting all of the related entities in the associated entity set

            try
            {
                using (var context = new Model1())
                {
                    var deleteEmp =
                        (from ed in context.EmployeeDept where ed.ID == edid select ed).FirstOrDefault();
                    foreach (EmployeeTask empTask in deleteEmp.EmployeeTasks)
                    {
                        context.EmployeeTasks.Remove(empTask);
                    }

                    context.EmployeeDepts.Remove(deleteEmp);
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Existing employee could not be deleted " + ex.ToString());
            }

where edid is variable. When I debugging by click F10 all executed correct until the line: context.EmployeeTasks.Remove(empTask); is executed and cursor returns back to in . After that I got error message: "System.Exception: 'Existing employee could not be deleted System.InvalidOperationException: Collection was modified; enumeration operation may not execute." What is a problem? How to fix it? Thanks.

Add .ToList() after deleteEmp.EmployeeTasks

foreach (EmployeeTask empTask in deleteEmp.EmployeeTasks.ToList())
{
    context.EmployeeTasks.Remove(empTask);
}

Could you try like this, but replace i.parentId for real navigation property

        try
        {
            using (var context = new Model1())
            {
                var deleteEmp = context.EmployeeDept.FirstOrDefault(i => i.id == deletedEmpId);
                var childEmps = context.EmployeeDept.Where(i => i.parentId == deletedEmpId).ToList();

                context.EmployeeDepts.RemoveRange(childEmps);
                context.EmployeeDepts.Remove(deleteEmp);
                context.SaveChanges();
            }
        }
        catch (Exception ex)
        {
            throw new Exception("Existing employee could not be deleted " + ex.ToString());
        }

Cause of your problem

In Entity Framework you can only Remove items that are in the DbContext.ChangeTracker . Every item in the ChangeTracker has a State that says whether it is Added / Modified / Removed.

When you call SaveChanges, the ChangeTracker is checked to see which items must be updated.

Whenever you fetch a complete items, so without using Select , the item is automatically stored in the ChangeTracker. There are other methods to add items to the change tracker, but those are out of scope of this question.

So all you need to do, is fetch all items that you want to Remove, before you remove them.

The solution

So you have Employees and EmployeeTasks . Apparently there is a one-to-many relation between Employees and EmployeeTasks : every Employee has zero or more EmployeeTasks ; every EmployeeTask belongs to exactly one Employee , namely the Employee that the foreign key EmployeeId refers to.

You need to fetch the Employee and all EmployeeTasks, remove all tasks, and then remove the Employee:

int employeeToRemoveId = ...
using (var dbContext = new EmployeeDbContext(...))
{
    var employee = dbContext.Employees.Find(employeeToRemoveId);
    if (employee != null)
    {
        // there is an employee with this Id. get its tasks:
        var tasksOfThisEmployee = dbContext.EmployeeTasks
            .Where(task=> task.EmployeeId == employeeToRemoveId)
            .ToList();

        // remove the tasks; remove the employee; save the changes
        dbContext.EmployeeTasks.RemoveRange(tasksOfThisEmployee);
        dbContext.Employees.Remove(employee);
        dbContext.SaveChanges();
    }
    // else: there is no Employee with this Id; nothing to do.
}

Simple comme bonjour!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM