2

Below are my 2 class sharing 1 to many relationship :

public partial class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Skills> Skills { get; set; }
}

public partial class Skills
{
    public int Id { get; set; }
    public Nullable<int> EmployeeId { get; set; }
    public string Skills { get; set; }
    public virtual Employee Employee { get; set; }
}

Now I am trying to remove employees with its corresponding skills in following way :

1) Deleting both employee and skills in 1 method with only save changes. I guess I will be having performance benefit in this case as I need to call save changes only once but there is also 1 issue that if skills got deleted but if error occurs while deleting employee in that case I will lose Skills of corresponding Employee.

public void Delete(int[] ids)
{
    using (var context = new MyEntities())
    {
        context.Skills.RemoveRange(context.Skills.Where(cd => ids.Contains(cd.EmployeeId)));
        context.Employee.RemoveRange(context.Employee.Where(t => ids.Contains(t.Id)));
        context.SaveChanges();
    }
}

2) Another option is to use transaction to make sure that both and child gets deleted successfully like below :

public HttpResponseMessage Delete(int[] ids)
{ 
    using (var context = new MyEntities())
    {
        using (var transaction = context.Database.BeginTransaction())
        {
            try
            { 
                DeleteSkills(ids,context);
                DeleteEmployees(ids,context);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                // throw exception.
            }
        }
    }
}

public void DeleteEmployees(int[] ids,MyEntities _context)
{
    _context.Employee.RemoveRange(_context.Employee.Where(t => ids.Contains(t.Id)));
    _context.SaveChanges();
}

public void DeleteSkills(int[] ids, MyEntities _context)
{
    _context.Skills.RemoveRange(_context.Skills.Where(cd => ids.Contains(cd.EmployeeId)));
    _context.SaveChanges();
}

3) I am looking for an option where I don't need to remove child (Skills) explicitly and child gets removed automatically based on removal of parent (Employee) entity like the way it happens in case of Code first Cascade on delete so that I don't have to fire 2 queries to remove parent and child (my first option) or I don't have to maintain transaction (my second option.)

I did some research but couldn't find any help on removing child automatically based on removal of parent in case of Database first approach (.edmx).

What is an efficient way to handle this scenario?

halfer
  • 19,824
  • 17
  • 99
  • 186
I Love Stackoverflow
  • 6,738
  • 20
  • 97
  • 216
  • 1
    I believe that `DbContext.SaveChanges` itself uses a transaction, so you don't have to worry about partial deletions in case 1 – Sam I am says Reinstate Monica Sep 27 '17 at 14:53
  • 2
    Why not use *SQL Cascade delete behavior* like this https://stackoverflow.com/a/37459049/2946329 – Salah Akbari Sep 27 '17 at 17:46
  • 1
    Hi Learning. I've noticed a number of problems with your posts, which could be avoided with some minor changes. Would you respond to these points please? (1) when referring to yourself, please always use a capital "I". Native English readers generally find it rather grating to read "i", and that minor frustration response can get in the way of assisting. (2) The words _wasn't, couldn't, don't, doesn't_ etc all have an apostrophe before the last letter. Would you be able to add that when you type it, or enable auto-correct on your computer? – halfer Sep 27 '17 at 18:27
  • (3) Each of your questions is religiously appended by the question "can anyone help me?". The answer to that is generally merely "yes", of course, but that's not the response you are seeking. The article [Why is “Can someone help me?” not an actual question?](https://meta.stackoverflow.com/questions/284236/why-is-can-someone-help-me-not-an-actual-question) is helpful here. If you can swap that phrase with a more specific question then that's great, otherwise please just leave it off. Thanks! – halfer Sep 27 '17 at 18:29
  • 1
    Why was this question reopened? I think the proposed duplicate was spot on. If not, what about [this one](https://stackoverflow.com/q/9005948/861716)? The crucial part is that the FK in the database should have cascaded delete specified. – Gert Arnold Sep 27 '17 at 21:01
  • @halfer I am really really sorry for the inconvinience but actually i am always in a hurry to ask the question and get my problem solved as quickly as possible because of the deadline so while posting question i dont check those minor things properly. – I Love Stackoverflow Sep 28 '17 at 07:25
  • @halferThe reason why i always say "Can someone please help me" in my question is just a request to SO users to help me – I Love Stackoverflow Sep 28 '17 at 07:27
  • @Learning: please try to take my advice at least in part, if only to reduce the amount of work you are giving, on an ongoing basis, to volunteer editors. Thank you. – halfer Sep 28 '17 at 09:15
  • @S.Akbari:Actually i havent tried it yet but while searching for cascade delete i came to know about circular cascade paths issue associated with that option – I Love Stackoverflow Sep 28 '17 at 13:27

2 Answers2

0

EF automatically deletes related records in the middle table for many-to-many relationship entities if one or the other entity is deleted.

Thus, EF enables the cascading delete effect by default for all the entities.

If you want manually handle you can use:

 .WillCascadeOnDelete(false);


 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<parent>()
            .HasOptional<child>(c => c.child)
            .WithMany()
            .WillCascadeOnDelete(false);
    }
0

Read about delete behaviour in Entity Framework.

You can choose how an enitity behave on delete so it can affect child/dependant.

In your case you need "Cascade" delete behaviour which automatically delete children/dependants of the entity you are deleting.

Do it like this in you OnModelCreating method:

 protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<PARENT>()
             .........
            .OnDelete(DeleteBehavior.Cascade);
    }

Take a look here on how to use and what is about:

https://entityframeworkcore.com/saving-data-cascade-delete#:~:text=Entity%20Framework%20Core%20Cascade%20Delete&text=Cascade%20delete%20allows%20the%20deletion,delete%20behaviors%20of%20individual%20relationships.

Flori Bruci
  • 436
  • 4
  • 11