-1

I'm trying to understand why Entity Framework works the way it does with deleting child entities!

I have a YogaSpace object/entity and a child entity called YogaSpaceImage. I want to delete a YogaSpaceImage from YogaSpace, so here is what I do.

This DOES NOT work

yogaSpace.Images.Remove(yogaSpaceImage);

to delete a child entity!

public string RemoveImage(int id, int imageIdToDelete)
{
        YogaSpace yogaSpace = _yogaSpaceRepository.Find(id);

        // delete image
        foreach (YogaSpaceImage yogaSpaceImage in yogaSpace.Images.OrderBy(m => m.Ordering))
        {
            if (yogaSpaceImage.YogaSpaceImageId == imageIdToDelete)
            {
                // check first to see if the deleted image is the first (primary) image, then make the 2nd image the yogaspace thumbnail
                if (yogaSpaceImage.Ordering == 1)
                {
                    yogaSpace.SpaceThumbnail = yogaSpace.Images.First(m => m.Ordering == 2).ImageThumbnail;
                }
                yogaSpace.Images.Remove(yogaSpaceImage);
            }
        } 
     }

     myRepository.InsertOrUpdate(YogaSpace);
     myRepository.Save()
}

This does work when I call myRepo.Removed(YogaSpaceImage).

public string RemoveImage(int id, int imageIdToDelete)
{
        YogaSpace yogaSpace = _yogaSpaceRepository.Find(id);

        // delete image
        foreach (YogaSpaceImage yogaSpaceImage in yogaSpace.Images.OrderBy(m => m.Ordering))
        {
            if (yogaSpaceImage.YogaSpaceImageId == imageIdToDelete)
            {
                // check first to see if the deleted image is the first (primary) image, then make the 2nd image the yogaspace thumbnail
                if (yogaSpaceImage.Ordering == 1)
                {
                    yogaSpace.SpaceThumbnail = yogaSpace.Images.First(m => m.Ordering == 2).ImageThumbnail;
                }

                _yogaSpaceRepository.Removed(yogaSpaceImage);  
            }
        } 
     }

     myRepository.Save()
}

Here is what Removed() and InsertOrUpdate() look like in my repo.

public void InsertOrUpdate(YogaSpace yogaSpace)
{
        if (yogaSpace.YogaSpaceId == default(int))
        {
            context.Entry(yogaSpace).State = System.Data.Entity.EntityState.Added;
        }
        else
        {
            context.Entry(yogaSpace).State = System.Data.Entity.EntityState.Modified;
        }
}

public void Removed(YogaSpaceImage yogaSpaceImage)
{
        context.Entry(yogaSpaceImage).State = EntityState.Deleted;
}

P.S. you would think InsetOrUpdate() in my repo would work for EntityState.Modified to remove a child entity?

P.P.S. not sure why I even need InsertOrUpdate(), it was built with the auto generated nuget package. If I don't use it and just call Save(), Entity Framework understands the changes I've made, so why the heck is it generated for me and why does entity.Added and entity.Modified even exist, because entities get saved and modified even if I don't explicitly calls these two?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
chuckd
  • 13,460
  • 29
  • 152
  • 331
  • Possible duplicate of [How to remove child one to many related records in EF code first database?](http://stackoverflow.com/questions/16654828/how-to-remove-child-one-to-many-related-records-in-ef-code-first-database) – BJ Myers Mar 26 '16 at 02:28

1 Answers1

3

A nice little trick is to use the parent's id in the child's primary key:

public class Parent
{
    public int Id { get; set; }

    public virtual List<Child> Children { get; set; }
}

public class Child
{
    public int Id { get; set; }

    public int ParentId { get; set;}
}

And the configuration:

modelBuilder.Entity<Parent>()
            .HasMany(x => x.Children)
            .WithRequired()
            .HasForeignKey(x => x.ParentId);

modelBuilder.Entity<Child>()
            .HasKey(x => new { x.Id, x.ParentId})
            .Property(x => x.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

This way when you remove a child from the parent, the ParentId cannot be empty and EF will mark the child for deletion.

Example how to add/remove child to parent:

using(var db = new DbContext())
{
    var p = db.Parents.First();
    var c = new Child();
    p.Children.Add(c);
    db.SaveChanges(); // Child was saved to the database

    p.Children.Remove(c);
    db.SaveChanges(); // Child will be deleted from the database

    p.Children.Clear();
    db.SaveChanges(); // All Child of this parent will be deleted
}
Chris
  • 2,009
  • 1
  • 16
  • 25
  • is there a way to do this with attributes? I'm not using your system (can't remember the name) for defining relationships and keys. Just a side note, I do have a ref id to the parent entity. I define it in my object like [Index] public int YogaSpaceRefId { get; set; }[ForeignKey("YogaSpaceRefId")] public virtual YogaSpace YogaSpace { get; set; } and public virtual ICollection Images { get; set; } – chuckd Mar 26 '16 at 07:29